Alessandro Del Sole's Blog

/* A programming space about Microsoft® .NET® */
posts - 159, comments - 0, trackbacks - 0

My Links

News

Your host

This is me! This space is about Microsoft® .NET® and Microsoft® Visual Basic development. Enjoy! :-)

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.

Microsoft MVP

My MVP Profile

I'm a VB!

Watch my interview in Seattle

My new book on VB 2015!

Pre-order VB 2015 Unleashed Pre-order my new book "Visual Basic 2015 Unleashed". Click for more info!

My new book on LightSwitch!

Visual Studio LightSwitch Unleashed My book "Visual Studio LightSwitch Unleashed" is available. Click the cover!

Your visits

Follow me on Twitter!

CodePlex download Download my open-source projects from CodePlex!

Article Categories

Archives

Post Categories

.NET Framework

Blogroll

Help Authoring

Microsoft & MSDN

Setup & Deployment

Visual Basic 2005/2008/2010

WPF: master-details sample with the DataGrid control and Visual Basic 2008

The WPF Toolkit, an open source controls library that completes the standard ones offered by WPF, exposes a new DataGrid control for WPF developers working on .NET Framework 3.5 SP 1. Before going on reading this blog post, you'll need to download and install the WPF Toolkit.

 

In this post I'd like to show you how to build a simple master-details sample built on the top of the ADO.NET Entity Framework and using the DataGrid for presenting and editing tabular data. In our code example we'll retrieve the customer's list for our virtual Northwind Traders company and will allow viewing and editing orders for each customer. Our demo will be split into two parts: the first one (this blog post) where we'll build the application accepting the default layout and settings for the DataGrid. In the second one (next blog post) we will learn how to customize DataGrid's cell with custom controls, so that we can make it more user friendly.

 

You can just run Visual Basic 2008 Express Edition to create the following demo. First, create a new WPF project. Second, add a new Entity Data Model based on the Northwind database. We need just the Customers and Orders tables from the database. If you need help with the Entity Data Model wizard and designer, please take a look at the How-do-I videos by MSDN.

 

Now I want to show you how the main Window will look like after designing the UI:

 

 

 

Let's switch to the XAML code editor so that we can begin defining the UI. First of all, let's divide the Grid into three rows:

 

    <Grid>

        <Grid.RowDefinitions>

            <RowDefinition Height="30"/>

            <RowDefinition/>

            <RowDefinition Height="50"/>

        </Grid.RowDefinitions>

 

In the first row we can place a ComboBox, that will allow users to select a customer from the list. Here is the code:

 

            <ComboBox ItemsSource="{Binding}" Name="CustomersCombo" Grid.Row="0"

                  IsSynchronizedWithCurrentItem="True" DisplayMemberPath="CompanyName"/>

 

The ComboBox will be populated via data-binding (ItemsSource); it's worth mentioning the DisplayMemberPath which specifies what property of the bound data source will populate the control.

 

Next, from the Visual Basic 2008 Express toolbox let's drag a DataGrid onto the designer's surface (you can find it in the WPF Toolkit tab). This step will add a reference to the WPFToolkit.dll assembly (which was installed to the GAC) and an XML namespace declaration within the Window element, so that we can use controls offered by the toolkit:

 

    xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"

 

Notice that you may receive an error message while draggin'n'dropping the control. If this is your case, you should manually perform the above described operations. At this point you'll be able to notice a new object added to the XAML code: the DataGrid one. Using the Property Window or writing code, let's edit the object as follows:

 

        <my:DataGrid Name="OrdersDataGrid" Grid.Row="1" IsSynchronizedWithCurrentItem="True"

                     AutoGenerateColumns="True" AlternatingRowBackground="Azure"

                     ItemsSource="{Binding}" CanUserAddRows="True" CanUserDeleteRows="True"

                     CanUserSortColumns="True" CanUserReorderColumns="True"

                     CanUserResizeColumns="True" CanUserResizeRows="True"/>

 

Some interesting points: first, the automatic generation of columns (AutoGenerateColumns), second the color selection for alternate rows (AlternatingRowBackground), last a series of properties that can modify contents layout inside the grid. 

It's worth mentioning that we don't have the need (as instead happens when using the ListView) of manually adding columns, because the DataGrid is able to accomplish this task for us. In the next post we'll see how to replace the default behavior.

 

At last, we can add a series of buttons:

 

        <StackPanel Grid.Row="2" Orientation="Horizontal"  >

            <Button Width="100" Height="30" Margin="5" Content="Add order" Name="AddButton"/>

            <Button Width="100" Height="30" Margin="5" Content="Delete order" Name="DeleteButton"/>

            <Button Width="100" Height="30" Margin="5" Content="Save changes" Name="SaveButton"/>

        </StackPanel>

    </Grid>

 

If no error is thrown, your window should look like the picture we saw at the beginning of this post. Let's now switch to the Visual Basic code editor for the code-behind file. At class level, let's first declare the following two objects:

 

    Private NorthwindContext As New NORTHWNDEntities

    Private OrdersList As ObservableCollection(Of Orders)

 

The first object gets the instance of the ObjectContext. The second one is an ObservableCollection, a particular collection for WPF that supports the two-way data-binding. We'll populate the collection with our data and then will bind it to the UI. In this way, manipulating the collection will reflect changes to the UI.

 

We can write two methods, one for getting the list of customers and one for retrieving orders based on the given customer (see comments):

 

    Private Function GetCustomers() As IQueryable(Of Customers)

        'Retrieves customers

        Return Me.NorthwindContext.Customers

    End Function

 

    Private Function GetOrders(ByVal CustomerID As String) As ObservableCollection(Of Orders)

 

        'Eager loading using Include. This is important because

        'we'll than set relationships

        Return New ObservableCollection(Of Orders) _

                (From ord In Me.NorthwindContext.Orders.Include("Customers") _

                Where ord.Customers.CustomerID = CustomerID _

                Select ord)

 

    End Function

 

Particularly the second method returns an ObservableCollection; this is because such object will be able to receive changes to data it stores. Next step is populating the ComboBox with the list of customers:

 

    Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Me.CustomersCombo.ItemsSource = Me.GetCustomers

    End Sub

 

Now we can handle the SelectionChanged event in the Combo, that is raised when the user selects a customer:

 

    Private Sub CustomersCombo_SelectionChanged(ByVal sender As System.Object, _

 ByVal e As System.Windows.Controls.SelectionChangedEventArgs) _

 Handles CustomersCombo.SelectionChanged

 

        'The instance of the customer selected in the combo

        Dim currentCustomer As Customers = CType(Me.CustomersCombo.SelectedItem, Customers)

 

        'Passing the CustomerID to the GetOrders method and populating the collection with the result

        Me.OrdersList = Me.GetOrders(currentCustomer.CustomerID)

        'Assigning the data source to the DataGrid

        Me.OrdersDataGrid.ItemsSource = Me.OrdersList

 

    End Sub

 

The ObservableCollection(Of Orders)that we obtained invoking the GetOrders methods and that populates the OrdersList object becomes the DataGrid's data source. Assigning the ItemsSource property is the step that finalizes data-binding. Now let's go on writing event handlers for buttons. First of all, the Save button:

 

    Private Sub SaveButton_Click(ByVal sender As System.Object, _

                                 ByVal e As System.Windows.RoutedEventArgs) _

                                 Handles SaveButton.Click

 

        Try

            Me.NorthwindContext.SaveChanges()

        Catch ex As Exception

            MessageBox.Show(ex.ToString)

        End Try

    End Sub

 

As you probably know, invoking the ObjectContext.SaveChanges will persist data versus the underlying database. This is how we can handle the addition of a new order:

 

    Private Sub AddButton_Click(ByVal sender As System.Object, _

                                ByVal e As System.Windows.RoutedEventArgs) _

                                Handles AddButton.Click

        Dim ord As New Orders

        ord.Customers = CType(Me.CustomersCombo.SelectedItem, Customers)

 

        Me.OrdersList.Add(ord)

 

        Me.NorthwindContext.AddToOrders(ord)

    End Sub

 

New order's instance receives the assignment of the Customers property. This will set the relationship. The customer was determined getting the current customer selected in the combo. So the new order is added to the ObservableCollection and to the context.

At last, the code for removing an order from the DataGrid:

 

    Private Sub DeleteButton_Click(ByVal sender As System.Object, _

                                   ByVal e As System.Windows.RoutedEventArgs) _

                                   Handles DeleteButton.Click

 

        Try

 

            Dim currentProduct As Orders = CType(Me.OrdersDataGrid.SelectedItem, Orders)

 

            Me.OrdersList.Remove(currentProduct)

            Me.NorthwindContext.DeleteObject(currentProduct)

 

        Catch ex As Exception

 

        End Try

    End Sub

 

At this point we can finally run the application and get the following result:

 

 

 

We can edit existing data, add or remove items working with cells. Clicking the Save Changes button will persist data to the Northwind database.

 

As I mentioned before, this is the default DataGrid layout, moreover there are automatically generated columns that are unnecessary. In next post we'll see how to customize the DataGrid working on cells' DataTemplate and manually adding columns.

 

You can download the source code for this blog post from the MSDN Code Gallery at this address.

 

Alessandro

Print | posted on venerdì 3 aprile 2009 16:47 | Filed Under [ Visual Basic Windows Presentation Foundation ]

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 8 and 5 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET