XAML Creating GridView from Code Behind - c#

I am practicing to learn XAML, but syntax is too verbose at my first impression. I am trying to create a gridView from codebehind like below:
var gv = new GridView();
gv.Name = "itemGridView";
gv.ItemsSource = sampleDataGroups;
gv.SetValue(AutomationProperties.AutomationIdProperty, "ItemGridView");
gv.SetValue(AutomationProperties.NameProperty, "Grouped Items");
gv.Padding = new Thickness(116, 137, 40, 46);
Grid.SetRowSpan(gv, 2);
While I can set my gridView' padding like a property, why I am using a static method of grid class to set its rowSpan ?
What is the reason behind that decision ?
Note: I guess I can write an extension method to do that but I am curious why it is not made at the beginning.

The reason is - a GridView (or pretty much every other control except the Grid itself) doesn't have a RowSpan property. Neither do these controls have the Row, Column and ColumnSpan properties.
Don't believe me? Check out the MSDN documentation for GridView. ;)
These are properties which you can use when you put something inside a Grid. Note that in XAML, you also set these properties up in a slightly different fashion: Grid.Row="1" as opposed to just Padding="2".
You can also set up the Grid properties as you did with AutomationProperties. The Grid.SetRowSpan is just a shorthand.

Because setrow and setrowspan are attached properties which are available to gridview's parent GRID which decides the measuring and the layout of the children and hence are not directly available to the children (gridview).

Related

How can I change the cell content in a ListView through code?

I'm dynamically creating a WPF window with a grid-like presentation. There is a header row that contains the column headers. It must always be visible. Below that there is a large number of rows (like hundreds) that can be vertically scrolled. Each row contains a text in the first column and a checkbox in each remaining column.
The list of columns and rows is dynamic, so creating a viewmodel class and binding with templates doesn't work (or would at least be very complicated and require much code while giving up the dynamic nature of the problem). Also, with each checkbox interaction in one row, all other rows might be affected (for the same column) and need to be updated. This would need a lot of interaction between all individual row viewmodels.
I'm looking for a solution to create the columns and rows of an existing empty ListView control and populate all of its data, checkboxes and interaction entirely in C# code.
Specifically I'm missing some ListView method that lets me set the content of a specific cell. While I can add columns to the ListView's GridView.Columns collection, I can't go anywhere from there without templates and bindings. Is is possible to use WPF like this?
The problem is that when I use a template for, say, a checkbox column, all checkboxes do exactly the same an no customisation is possible anymore because I don't create each checkbox, instead WPF creates them for me.
You may create a specific CellTemplate for each GridViewColumn using either XamlReader.Parse:
const string Xaml = "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x = \"http://schemas.microsoft.com/winfx/2006/xaml\">" +
"<CheckBox Content=\"{Binding Name}\" IsChecked=\"{Binding IsChecked}\" />" +
"</DataTemplate>";
column.CellTemplate = XamlReader.Parse(Xaml) as DataTemplate;
...or a FrameworkElementFactory:
FrameworkElementFactory checkBox = new FrameworkElementFactory(typeof(CheckBox));
checkBox.SetBinding(CheckBox.ContentProperty, new Binding("Name"));
checkBox.SetBinding(CheckBox.IsCheckedProperty, new Binding("IsChecked"));
column.CellTemplate = new DataTemplate() { VisualTree = checkBox };
This lets you customize the columns but still use the GridView and its functionlity the way you are supposed to. Trying to modifying the generated visual elements is not recommended, especially not if you are using the UI virtualization.

Telerik RAD Controls, how to set a List(Of GridViewRowInfo) as a RadGridView DataSource?

I'm looking for a C# or VB.NET solution for this.
UPDATE:
I have a RadGridView with 5 manualy defined columns by me:
AutoGenerateColumns property is set to False.
When I instace a GridViewRowInfo class I can set a lot of properties for this object:
Dim MyRow As New GridViewRowInfo(Me.RadGridView1.MasterView)
With MyRow
.Cells(0).Value = "My Value for Column 1"
.Cells(1).Value = "My Value for Column 2"
.Cells(2).Value = "My Value for Column 3"
.Cells(3).Value = "My Value for Column 4"
.Cells(4).Value = "My Value for Column 5"
.Height = 50
.Tag = New Object
.IsSelected = True
End With
And when I add that row the properties that I've previously set for that row takes effect inmediately:
RadGridView1.Rows.Add(MyRow)
If I want to add a collection of those rows just I can set a new collection of GridViewRowInfo that implements the IList interface:
Dim MyRows As New List(Of GridViewRowInfo)
MyRows.Add(MyRow1)
MyRows.Add(MyRow2)
MyRows.Add(MyRow3)
RadGridView1.Rows.AddRange(MyRows.ToArray)
Well, so my intention is to set a collection of those rows as DataSource, for example:
RadGridView1.DataSource = MyRows
So the first thing to notice is that I've set a collection of GridViewRowInfo and I've set different properties for each GridViewRowInfo that should take effect when adding the datasource-collection, the second thing is that if I update the datasource-collection to remove or add more rows then the RadGridView control should perform the updates automatically without more intervention ...not?
The problem is that any of those things happens:
As you could see in the image above, when I set a List(of GridViewRowInfo) as my DataSource, it only adds empty rows, and if I previously have set for example the Height property of one of the GridViewRowInfo inside it does not take effect when setting the Datasource:
I would like to perform this in the more direct way and the less extravagant way, I mean i'm not looking for create a custom class to be able to set that class as DataSource, and reproducing all the properties that exposes the GridViewRowInfo class or something so tricky in my custom class, 'cause If the RadGridView exposes a good GridViewRowInfo class with all that I need why I should consider to create a custom class to set it aa my DataSource?.
If I don't have a good idea or a missunderstanding of these concepts please clarify me them, I know that the usage of the datasource should not be used in that way (or I think so) but I really would like to do it to simplify the things even more to work directly with the datasource (and each row property) instead the control itself.
Also I've tried the oficial example in this link (but just using a list(Of String) instead), but it just adds a new column in my gridview named 'Length' (with a numeric data) in that column cell.
RadGridView supports two ways of populating with data:
Unbound mode where you can manually add the columns and the rows to the grid (just like you did)
Bound mode where you set the DataSource property of the control to one of the supported types, namely
Array and ArrayList of simple types or custom objects.
Generic Lists of simple types or custom objects.
BindingList or other IBindingList` implementations.
Database data using DataTable, DataSet or DataReader components from a wide range of providers (MS SQL, Oracle, Access,
anything accessible through OleDb).
So, you cannot bind the grid to collection of GridViewRowInfos (as you will only see the GridViewRowInfo type properties). You should either continue manually adding the as you are right now, or you can populate a DataTable for example with your data and set it as DataSource for the grid.
*All of the links and information are from the Telerik UI for WinForms documentation
If I don't have a good idea or a missunderstanding of these concepts please clarify them
You are confusing WHAT to display with HOW to display them which are 2 very different things. From their online guide: The RadGridView supports the standard Windows Forms data binding model which is to say the datasource provides data for the control, not presentation information.
Public Class MyObject
Public Property MyInt() As Integer
Public Property MyString() As String
...
Dim myList As New List(Of MyObject)()
myList.Add(New MyObject(1, "Outdoor"))
myList.Add(New MyObject(2, "Hardware"))
myList.Add(New MyObject(3, "Tools"))
myList.Add(New MyObject(4, "Books"))
myList.Add(New MyObject(5, "Appliances"))
RadGridView1.DataSource = myList
Result:
Note how the control automatically picks up the Property Names from the custom class: MyInt and MyString become column names. That is the only layout (HOW) related thing the grid picks up from the DataSource, and thats only when AutoGenerateColumns is True (otherwise they would be blank). When False, you control it by laying out the columns.
Now look at what you are attempting:
With MyRow
.Cells(0).Value = "My Value for Column 1"
.Cells(1).Value = "My Value for Column 2"
...
.Height = 50
.Tag = New Object
.IsSelected = True
There are many problems with this as a DataSource. Mainly, you are not supplying data for cells, but data in cells for cells. Your approach sort of mixes the unbound approach (explicitly specify what is to go into each cell), with binding to a datasource.
But, how is it supposed to know Value is a data display item? How is it supposed to know to drill into the cell collection to find Value? How is it supposed to know that Value is data but Tag is not? How is it supposed to know not to try to display Height as column data? Just because the name matches a control's property name?
What would happen if myObject by chance had a Height property related to my class? You want the control to interpret it as control layout information, but the rest of the world would want the patient's height, or building height or geo formation height to show as data. We would have to design classes with unique names not found in the control in order to get our data to show and prevent the control presentation from whimsically changing based on data and property names in the DataSource.
The GridviewRowInfo as the name suggests provides row information, not row data. Extensive presentation information is present in your List, but it doesnt work like you want because controls do not use the datasource to get presentation infomation.
The control does include Four ways to customize RadGridView appearance: Themes, UI editor, Events and Conditional Formatting.
There other elements like GridTableElement and GridTableBodyElement. Actually these elements contain some properties that control behavior and appearance of grid cells and rows, like GridTableElement.RowHeight, RowSpacing and so on.
tl;dr
Data passed in a DataSource, does not affect the presentation (aside from Column names with AutoGenerateColumns, but that is a function of that property, not the datasource.)

Set DataGridView rows after all are created to stop refresh

I'm adding a great deal of rows to a data grid view, and the process is pretty slow because it appears to try to redraw after each addition.
I'm having trouble finding an example online of how to create a List (or array, whichever works) of rows and add them all at once after the list is created. I need to do this to stop it from re-drawing after each addition though.
Can anyone provide a brief example of this or point me to a good doc?
You're probably looking for the DataGridView.DataSource property. See http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.datasource(v=vs.90).aspx
For example:
//Set up the DataGridView either via code behind or the designer
DataGridView dgView = new DataGridView();
//You should turn off auto generation of columns unless you want all columns of
//your bound objects to generate columns in the grid
dgView.AutoGenerateColumns = false;
//Either in the code behind or via the designer you will need to set up the data
//binding for the columns using the DataGridViewColumn.DataPropertyName property.
DataGridViewColumn column = new DataGridViewColumn();
column.DataPropertyName = "PropertyName"; //Where you are binding Foo.PropertyName
dgView.Columns.Add(column);
//You can bind a List<Foo> as well, but if you later add new Foos to the list
//reference they won't be updated in the grid. If you use a binding list, they
//will be.
BindingList<Foo> listOfFoos = Repository.GetFoos();
dgView.DataSource = listOfFoos;
A handy event to bind to at that point is the DataGridView.DataBindingComplete which fires after the data source is bound.
Here are a couple of ideas:
1) Bind a list to the DataGridView. When you set the DataGridView.DataSource = MyList, it immediately updates the entire grid without all the line-by-line action. You can add the items to MyList and then rebind to the DataGridView. (I prefer using a BindingList which will update the DataGridView grid dynamically.)
2) If data binding is not an option, what I've done in the past is set the AutoSizeMode = NotSet for each column before the update and then set it back to whatever it was before. It is the AutoSizeMode that really slows down the drawing.

C# fill Dynamic Grid with TextBox, Button and more in WPF

VS2010 -C#
I have a TextBox where you can input an integer and a UniformGrid is dynamically generated with the integer number of UniformGrid Cells. Now if I want to add a TextBox to each UniformGrid Cell, I do the following (e.g. int is a 5):
TextBox[] tb = new TextBox[5];
for (int i = 0; i < 5; i++)
{
tb[i] = new Textbox();
UniformGrid1.Children.Add(tb[i]);
}
Ok..that works fine. But problem comes when I need also to fill in some more Texboxes, Buttons, and Labels in it with some design properties defined, possibly also insert a grid inside a UniformGrid Cell. It will get extremely messy if I create arrays for each control and define each array properties in the loop.
Not only that it's messy, I cannot put the textbox inside the UniformGrid's Cell's Grid. The children add the grid on top of the TextBox instead.
Is there a better way to approach this?
You should use DataBinding instead.
Make a ItemsControl bind it to ObservableCollection and use UniformGrid as a container to ItemsControl.
I think that using specialized controls like DataGrid would be better, beacuse it automatically creates two-way bindings to model, it's easy to maintain, etc. There are lots of examples, for example here (Google can help you to find more, if you ask something like "wpf datagrid example tutorial")

How do I dynamically create a DataGridView in C#?

How do I dynamically create a DataGridView in C#? Could you please provide an example?
You can create it like any other controls.
place a PLACEHOLDER control in your page (this will serve as start point)
so your page looks like
<body>
<form id="form" runat="server" />
<asp:PlaceHolder id="ph" runat="server" />
</body>
Then, in your code behind, just create and add controls to the Place Holder
// Let's create our Object That contains the data to show in our Grid first
string[] myData = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
// Create the Object
GridView gv = new GridView();
// Assign some properties
gv.ID = "myGridID";
gv.AutoGenerateColumns = true;
// Assing Data (this can be a DataTable or you can create each column through Columns Colecction)
gv.DataSource = myData;
gv.DataBind();
// Now that we have our Grid all set up, let's add it to our Place Holder Control
ph.Controls.Add(gv);
Maybe you want to add more controls?
// How about adding a Label as well?
Label lbl = new Label;
lbl.ID = "MyLabelID";
lbl.Text = String.Format("Grid contains {0} row(s).", myData.Length);
ph.Controls.Add(lbl);
// Done!
Hope it helps get you started
Based on your reply that you are using WinForms. First a very simple example, then a little discussion of issues to consider based on "typical" usage scenarios.
Here's a specific example where, in response to a click on a button at run-time, a new DataGridView is created, positioned on the Form, sized, etc. :
// declare a form scoped variable to hold a reference
// to the run-time created DataGridview
private DataGridView RunTimeCreatedDataGridView;
// sample of creating the DataGridView at run-time
// and adding to the Controls collection of a Form
// and positioning and sizing
// fyi: the Form used here is sized 800 by 600
private void button1_Click(object sender, EventArgs e)
{
RunTimeCreatedDataGridView= new DataGridView();
RunTimeCreatedDataGridView.Size = new Size(300, 542);
RunTimeCreatedDataGridView.Location = new Point(10,12);
this.Controls.Add(RunTimeCreatedDataGridView);
}
You can, of course simplify setting Size and Location using the Bounds property, or the method 'SetBounds as in :
RunTimeCreatedDataGridView.SetBounds(10,12,300,542);
You may wish to set other properties that determine Size and Location "automatically" by setting the Dock or Anchor properties.
And you will probably want to "custom configure" the DataGridView's visual appearance in other ways via adding calls to set BackGroundColor, BorderStyle, etc. to the above code.
By this time, I'd hope you are thinking something like: "what about the really important things like configuring the columns, databinding, etc. ?" What about all that wonderful functionality exposed at DesignTime by the "Smart Tag" on the DataGridView's upper right corner, and in the Property Browser window.
Here's where we get general, rather than specific.
If you are "sure" that at some point the run-time user is going to want to create a DataGridView: why not create it in advance: visually style it, create columns, etc., and then hide it when the Form Loads: then show it on demand.
If you absolutely must create a DataGridView from scratch at run-time, but want to avoid a lot of typing : first create the DataGridView at design-time, go into the Designer.cs file and copy out the automatically generated code that is useful for you for visual style, adding and configuring columns: then paste that code in the method or event where you create the DataGridView (yes, you'll need to 'tweak it a bit).
Since, in this case, we know nothing about what you might, or might not, be binding the DataGridView to, we'll just stay "mum" on that one.
In (the odd ? off chance ?) the unlikely case you are creating multiple DataGridViews at run-time, suggest you maintain an internal list of them in a variable like List<DataGridView> and have one variable named currentDataGridView that you can rely on to hold a reference to the currently active (has focus, is visible, etc.) DataGridView.
In every case I recommend using "messing around" with a DataGridView in design-time mode, and then examining the code produced in the Designer.cs file (but never altering it !) to get quick information on how to use various features of the DataGridView. And for major examples of binding a DataGridView to complex DataSources and formatting: do check out CodeProject for relevant articles, tips, etc.
"Harvest" what you need from the automatically generated code in Designer.cs file, and then, when you are ready, delete the DataGridView instance on a Form, and "do your own thing" at run-time.
GridView gv = new GridView();
gv.datasource = dt;
gv.databind();
and then place this gv in panel or div or table coloumn.
You can check this link http://www.ehow.com/how_5212306_create-datagridview-c.html

Categories

Resources