Using the WPF .NET 4.0 DataGrid
Written by Mike James   
Thursday, 23 December 2010
Article Index
Using the WPF .NET 4.0 DataGrid
More columns
Accessing Data

Banner

External IEnumerables

It is easy enough to make use of the Items collection supplied along with the DataGrid but most of the time the data that is displayed comes from an external source - typically a database connection. It is easy to get a DataGrid to use an external collection object. All you have to do is set its ItemsSource property. To see this in action we first create a suitable object type to hold the data:

 public class Person
{
  public string name { set; get; }
  public int age { set; get; }
  public bool member { set; get; }
  }

Then we create a collection of these objects:

 List<Person> myList = 
new List<Person>();
myList.Add(new Person()
{name="john",age=25,member=true});
myList.Add(new Person()
{name="jill",age=25,member=false});
myList.Add(new Person()
{name="bill",age=15,member=true});

At the end of this code block MyList contains three Person objects suitably initialised. All we have to do to make the DataGrid display this collection is:

 dataGrid1.ItemsSource=myList;

After this assignment the DataGrid's Items property references and hence uses myList.

We can also get the grid to generate the necessary columns with the correct bindings for us by setting its AutoGenerateColumns property to true. In fact as this is its default we generally get the columns autogenerated without having to do anything. The result is a three-column grid with two DataGridTextColumns and one DataGridCheckBoxColumn. You could have added and bound the three columns in code using the same sort of code used earlier.

datagrid5

 

There is a subtlety hidden here. The ItemSource property references the original list, i.e. MyList, but the Items property references an ItemCollection which the List has been converted to. It is always the derived ItemCollection which is used to display the data. This means that there is always a current item and you can use the ItemCollection methods to move the current position. Notice also that the original variable that references the collection you assign to the DataGrid can  go out of scope without any problem as the DataSource property still provides a reference to the object.

Data editing

The easiest way of editing the data in the DataGrid is to simply set the properties that allow the user to do the job interactively. You can set or unset CanUserAddRows, CanUserDeleteRows, CanUserReorderColumns and so on. Just look up properties that start with "Can". Notice that if the user adds a row or modifies the data then the modifications are made to the collection assigned to ItemsSource. This isn't an example of two way databinding, in fact databinding isn't being used - it is simply that the collection providing the data that the DataGrid shows is used to store the new or modified data.

Now we come to the subject of editing data from code and this is where the questions about rows, columns and even cells tend to crop up. If you have followed the discussion of how the DataGrid works then you will be quite clear that there is no need to think in terms of rows or columns or cells for that matter. The raw material of the DataGrid is a collection of objects which roughly correspond to the rows in the alternative model and each object has a collection of properties which correspond to the columns or the cells depending on how you want to look at it.

However there are equivalents of the row and column oriented access methods and they are sometimes useful.

To access a "cell" value

To access the data stored in the grid at a given row and column you would retrieve the item that represents the row, cast it to the correct type and use the property that corresponds to the column. For example, to retrieve the name of the first item in the DataGrid in the previous example:

 string name =
((Person) dataGrid1.Items[0]).name;

To modify a "cell" value

To modify a cell value at a given row and column you simply use the recipe given above but assign to the property. For example to change the value of the name in the first item in the DataGrid in the previous example you would use:

((Person)dataGrid1.Items[0]).name = "Tom";

If you consider the situation for a moment then it is also clear that, as long as you still have a reference to it, you can modify the original collection just as easily as the grid. For example you could change MyList in the same way.

To access the currently selected row

This is just a matter of using the SelectedItem property:

 string name =
((Person) dataGrid1.SelectedItem).name;

To access the currently select cell

This is perhaps the most tricky thing to do and it takes us into the use of the Cell and CellInfo objects which is perhaps the closest we get to the traditional rows, columns and cells approach.

First we have to switch the DataGrid into cell selection mode using its SelectionUnit property:

 dataGrid1.SelectionUnit = 
DataGridSelectionUnit.Cell;

Now the user can select a block of cells. To access the selected cells we have to use the SelectedCells collection. This returns a collection of DataGridCellInfo objects. To select the first we would use:

 DataGridCellInfo cell = 
dataGrid1.SelectedCells[0];

Now we have a DataGridCellInfo object we can actually access the cell itself. This isn't the cell value however but whatever control is used to display the cell contents. In the case of a text column this is a TextBlock control. To retrieve this we have to use a complicated multi-step approach. First get the column that the cell is in:

 cell.Column

Now we can get the CellContent at the intersection of the column and the item that the selected cell is in:

 cell.Column.GetCellContent(cell.Item)

This returns a TextBlock which we can finally access the text stored in the cell, but only with the help of a suitable cast. Putting all this together gives:

 string value = 
((TextBlock)cell.Column.
GetCellContent(cell.Item)).Text;

This is convoluted and I have to admit that there might be a better way but this is typical of the sort of thing that happens once you have to go back to thinking in terms or rows, columns and cells. Much better to think of collections of objects, columns and properties.

For more on the DataGrid: stay tuned to iProgrammer.

To see an example of the DataGrid in action with an ADO .NET database then see: Windows Search (WDS 4.0).

If you have any questions about the DataGrid, suggestions for further articles or any comments  email the editor.

Banner


Custom Shape

Creating a custom Shape isn't difficult but it does have some hidden gotchas. We take a look at how best to do the job.



WPF .NET Core - Inside Dependency Properties

One of the great mysteries of WPF is the strangely named "Dependency Properties". In this chapter we learn how dependency properties really work by creating a custom dependency property



Loading Bitmaps: DoEvents and the closure pattern

Sometimes loading a bitmap causes an asynchronous download and you have to wait for it to complete before using it - but how best to wait? The standard solution is to use an event but this breaks what [ ... ]



Comparative Analysis of Browser Protection Software and Coding Practices

The digital space is awash with an array of threats, from hackers to malware and viruses, making browser protection software and secure coding practices crucial to safeguarding data. As tech [ ... ]



Bitmap Effects

WPF bitmap effects are easy to use but subtle. Before moving on to consider custom effects we take a careful look at what is provided as standard.


Other Articles

<ASIN:0735625735>

<ASIN:1430224819>

<ASIN:0470499834>

<ASIN:1430224355>

<ASIN:1430223812>



Last Updated ( Thursday, 16 May 2013 )