DataGrid
and the ObservableCollection
In most cases you perform data-binding operations against .NET collections, even when fetching data from databases. WPF offers a different binding mechanism, such as user controls like the new DataGrid
, the ListView
, or the ListBox
; moreover you can bind specific data to single controls like TextBox
(for example when building master-details representations). In this book, which targets Visual Basic 2010 and .NET 4.0, you get an example of how to take advantage of the new DataGrid
control, which offers a convenient and fast way for tabular data. The goal of next example is binding a collection of objects to a DataGrid
allowing insert/update/delete operations onto the collection. First, add a new implementation of the Person
class to the project as follows:
Now add a new People
class, which inherits from ObservableCollection(Of Person)
as follows:
This new collection is the data source for binding to the DataGrid
. Now go the VB code behind the file for the main window. Basically we need to declare a variable of type People
and handle the Window_Loaded
event to instantiate some Person
objects to populate the collection. The following code accomplishes this:
Notice how easy it is to create an instance of the People
collection with collection initializers. The most important thing here is the assignment of the Grid.DataContext
property. As a general rule, DataContext
is a property that points to a data source, and all children controls within the panel that exposes the DataContext
property will populate picking up data from this property. This also means that DataContext
has scope; for example, the Window.DataContext
property can share data to all controls in the user interface, whereas the DataContext
from a particular panel can share data only with controls nested in that particular panel, as in the previous code example where only controls nested in the Grid
(including thus the DataGrid
) can populate picking data from the DataContext
. This is not mandatory. If you have a single control that you want to bind, you do not need to assign the DataContext
, whereas you can simply assign the specific control data property. For instance, the DataGrid
control exposes an ItemsSource
property (like ListView
and ListBox
) that populates the control. Data-binding to user interface controls in WPF is generally possible thanks to the implementation of the INotifyPropertyChanged
interface. Substantially controls can reflect changes from data sources that implement that interface. The ObservableCollection(Of T)
generic collection also implements behind the scenes and therefore can notify the user interface of changes so that it can be refreshed automatically. This is the reason why we use such a collection in the example. This specialized collection is also interesting because it enables getting information on what changed on data. It exposes a CollectionChanged
event that offers an e
argument of type NotifyCollectionEventArgs
that offers some useful information. For example it enables intercepting when an item is added or removed or retrieving a collection of added items. Continuing with the example, suppose you want to create a sort of log to write a message each time an item is added or removed from the source
collection. This is useful for demonstrating that the collection is effectively updated with changes performed through the user interface. The second TextBox
in the user interface of the sample application is the place where log messages will be put. According to this consideration, consider the following code snippet that provides an event handler for the CollectionChanged
event:
The code simply sends to the text box the current value of the System.Collection.Specialized.NotifyCollectionChangedAction
enumeration, which can be one of the following: Add
, Remove
, Move
, Replace
, or Reset
. If you perform multiple CRUD operations on an ObservableCollection
instance, you might also be interested in the NewItems
and OldItems
properties in e
. They respectively represent a collection of items added to the data source and a collection of items affected by a remove, replace, or move operation. Before running the application, it is necessary to perform a couple of operations on the DataGrid
at the XAML level; therefore switch back to the XAML code editor. Extend the DataGrid
declaration as follows:
First, the DataGrid
automatically generates columns for you according to each property exposed by a single item (Person
) in the bound collection (People
). Second, the ItemsSource
, which populates the control, is set to Binding
with no arguments meaning that the data-binding will be performed at runtime. Notice how the AlternatingRowBackground
property enables specifying a color (which you can eventually replace with a brush) for the background in alternating rows. Now run the application. You get the result shown in Figure 35.2.
If you play with the DataGrid
you can easily understand how it enables adding, removing, and editing items. The log text box stores messages each time you perform an operation, confirming that the underlying collection is actually affected by changes performed through the user interface. You can then plan to implement some code for saving your data. The DataGrid
exposes other interesting properties:
• SelectedItem
, which returns the instance of the selected object in the control
• CurrentCell
, which returns the content of the selected cell
• CanUserAddRows
and CanUserRemoveRows
, which respectively provide (or not) the user the ability of adding and deleting rows
• CanUserReorderColumns
, CanUserResizeColumns
, CanUserSortColumns
which respectively provide (or not) the ability of changing the order of resizing and sorting columns
• CanUserResizeRows
, which provides (or not) the ability of resizing rows
• RowStyle
, which allows overriding the style for rows
Until now you saw simple data-binding tasks, although the last code example provides a good way for understanding the mechanism. WPF data-binding is even more complex and the .NET Framework offers specific objects that are important in more articulate scenarios. The next section describes such objects taking advantage of new Visual Studio features.
18.191.199.227