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 a customized DataGrid and Visual Basic 2008

In my previous blog post I discussed about creating a small "master-details" example within a WPF application, writing Visual Basic code. We learnt how setting up the new DataGrid control from the WPF Toolkit for presenting and editing data using the default layout.

 

The DataGrid is a flexible control. It allows to customize columns so that the UI gets more user friendly. This is accomplished customizing cells' template. There are some native templates, such as the following: 

 

·         DataGridTextColumn, which allows viewing/editing text;

·         DataGridCheckBoxColumn, which allows viewing and settings boolean value via a CheckBox;

·         DataGridComboBoxColumn, which allows selecting values to be assigned to cells via a ComboBox;

·         DataGridHyperLinkColumn, which allows assigning an Hyperlink to the specified cell's content;

·         DataGridTemplateColumn, which allows defining custom templates for cells, e.g. aggregating native WPF controls.

 

The default layout for the DataGrid is substantially based on the DataGridTextColumn but often this is not the right choice for types different than text. For example, we could decide to implement a DatePicker control for editing orders' date/time, and that is where the custom templates come. 

 

Let's retake the previous code example and do some edits. First, we'll show only some columns of the Orders table. Second, we'll format currency fields with the appropriate symbols. Third, we'll format as Hyperlinks the name of the Ship Cities and enable a Live Maps search. At last, we'll implement the DatePicker so that users will be able to edit orders' date/time via a specific control.

 

So, let's go back to the XAML code editor. First of all, let's edit the code that declares the DataGrid as follows:

 

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

                     AutoGenerateColumns="False" AlternatingRowBackground="Azure"

                     ItemsSource="{Binding}" >

 

It's worth mentioning that the AutoGenerateColumns is now set as False. Columns must be enclosed within a DataGrid.Columns element. The first column will show the OrderID:

 

            <my:DataGrid.Columns>

                <my:DataGridTextColumn Header="Order ID" Binding="{Binding Path=OrderID}"/>

 

The Header property establishes the column header, while the Binding one determines the object that must be bound to the control. In this case we need to present just text, so we used a DataGridTextColumn.

 

Now, let's implement a column for showing the OrderDate property's value. We must declare a DataGridTemplateColumn so that we can define a custom DataTemplate for the cells of this column. The interesting thing is that we can define behaviors both for presenting and for editing data. For example, we could show data via TextBlock, while we could edit data via DatePicker. This is the code that declares the new column:

 

                <my:DataGridTemplateColumn Header="Order Date">

                    <my:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock Text="{Binding Path=OrderDate, StringFormat='D'}"/>

                        </DataTemplate>

                    </my:DataGridTemplateColumn.CellTemplate>

                    <my:DataGridTemplateColumn.CellEditingTemplate>

                        <DataTemplate>

                            <my:DatePicker SelectedDate="{Binding Path=OrderDate, Mode=TwoWay, StringFormat='D'}"/>

                        </DataTemplate>

                    </my:DataGridTemplateColumn.CellEditingTemplate>

                </my:DataGridTemplateColumn>

 

In a few words, the DataGridTemplateColumn.CellTemplate object allows specifying the way for presenting data. In this case we can just implement a TextBlock, and use the StringFormat on the binding markup extension to show the long date format.

The DataGridTemplateColumn.CellEditingTemplate object is instead the one which allows specifying the way for editing data. By implementing a DatePicker control we can allow our users to select dates via a specific control instead of manually writing text. The bound property is the SelectedDate that is set as TwoWay (this will ensure that UI and underlying data are going to the same direction).

 

Next column is the Freight one. It should represent transportation costs, so we can show it as text but format as currency: 

 

                <my:DataGridTextColumn Header="Freight" Binding="{Binding Path=Freight, StringFormat='c'}"/>

 

The last column we want to implement is about the Ship Cities. It would be a good idea to present the name of the City as hyperlink and start a Live Maps search so that our user can easily understand where the city is:

 

                <my:DataGridHyperlinkColumn Header="Ship Country" Binding="{Binding Path=ShipCountry}">

                    <my:DataGridHyperlinkColumn.ElementStyle>

                        <Style TargetType="TextBlock">

                            <EventSetter Event="Hyperlink.RequestNavigate" Handler="OnHyperLinkClicked" />

                        </Style>

                    </my:DataGridHyperlinkColumn.ElementStyle>

                </my:DataGridHyperlinkColumn>

            </my:DataGrid.Columns>

           

        </my:DataGrid>

 

Notice how an ElementStyle is used: here we can specify what events should be handled (in this case the RequestNavigate). Now let's switch to the code-behind file; we can leave unchanged the previous code and add an event handler for the RequestNavigate:

 

    Private Sub OnHyperlinkClicked(ByVal sender As Object, _

                                   ByVal e As RequestNavigateEventArgs)

 

        'The e.Uri property contains the text stored in the HyperLink,

        'which is the name of the city, in our case

        Dim link As New Uri("http://maps.live.com/?q=" + _

                            e.Uri.ToString + "&mkt=it-IT&FORM=BYRE")

 

        Process.Start(link.ToString)

    End Sub

 

Please consider that in the above search string settings are for Italian regional settings, so you should rewrite the search string according to your preferences. Now let's try and run the application; the following picture is an example of what we should get:

 

 

 

As you can easily understand, this is surely a much better approach!

 

You could also manage columns at design time. If you assign a data source to the DataGrid in XAML (e.g. via an ObjectDataProvider), you can utilize the Visual Studio designer (Properties window -> Columns). The following picture shows the columns editor window:

 

 

 

The updated version of the source code is available from this address.

 

Alessandro

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

Feedback

No comments posted yet.

Post Comment

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

Powered by:
Powered By Subtext Powered By ASP.NET