Understanding the 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:

image

Now add a new People class, which inherits from ObservableCollection(Of Person) as follows:

image

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:

image

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:

image

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:

image

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.

Figure 35.2 The data-bound DataGrid allows presenting and manipulating data.

image

DataGrid Binding Tips

Different from controls such as the ListView and the ListBox, the DataGrid allows binding any collection implementing IList or IBindingList. This is because such control requires a place for editing, other than presenting. So remember this requirement when you try to bind to a DataGrid the result of LINQ queries, which requires conversion into a generic collection. For LINQ, if you try to bind LINQ to Xml, query results also remember to create a class for holding objects, just like the Person class and People collection instead of directly binding the query result.

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.199.227