Thursday, August 9, 2018

UWP Tip #22 - Windows Community Toolkit 4.0 Released - DataGrid Is Ready For Your Production Apps

New Release

It's another milestone for the Windows Community Toolkit. Yesterday on the Windows Developer blog, Nikola Metulev announced that the Windows Community Toolkit v4.0 had been released. These are the major changes, according to the release notes on GitHub:
  • DataGrid control is now released out of preview
  • 2 Microsoft Graph controls were added:
  • WebView control enhancements
  • Services (Twitter, LinkedIn, MS Translator) moved Microsoft.Toolkit.Services. Anyone targeting .NET Standard 1.4 can now use these.
  • Twitter service enhanced to include some missing properties from Twitter tweet API
  • Windows Community Toolkit Sample App updated to implement fluent design and a dark theme!
  • Assembly strong naming
  • Dozens of bug fixes in controls, helpers, services and documentation

DataGrid Control

The DataGrid XAML control feel be immediately familiar to any developers who have used the Silverlight DataGrid. This control shares the functionality of the old Silverlight control. In fact, the docs for the DataGrid actually link to the Silverlight DataGrid's API for reference.
As usual, Microsoft's docs are a great place to start. There are eight How-To's for the DataGrid available, so I won't provide my own simple walkthrough here. Instead, let's explore DataGrid in the newly updated Windows Community Toolkit Sample App.
Open the sample app, and select the DataGrid from the Controls menu.
DataGrid01
As you can see, I'm already taking advantage of the addition of the dark theme support in the latest release of sample app.
You'll be presented with a DataGrid control filled with data about mountains. Let's take a minute to thank the developers who worked on the sample app for not providing users with yet another invoicing or inventory set of data.
DataGrid02
Speaking of Themes, did you notice another new feature of the sample app? You can select System, Light or Dark to apply themes to the individual controls displayed within the sample app. How useful!
Just below this, in the header area just above the DataGrid itself, users are able to Filter or Group the grid data with a set of AppBarButton controls. This is the default code for the header:
<StackPanel Orientation="Horizontal" Margin="12">
   <TextBlock Text="DataGrid Sample : Mountains" VerticalAlignment="Center" Margin="5,0" Style="{ThemeResource SubtitleTextBlockStyle}"></TextBlock>
   <AppBarButton Icon="Filter" Label="Filter by">
     <AppBarButton.Flyout>
       <MenuFlyout>
         <MenuFlyoutItem x:Name="rankLow" Text="Rank &lt; 50" />
         <MenuFlyoutItem x:Name="rankHigh" Text="Rank &gt; 50" />
         <MenuFlyoutSeparator />
         <MenuFlyoutItem x:Name="heightLow" Text="Height &lt; 8000ft" />
         <MenuFlyoutItem x:Name="heightHigh" Text="Height &gt; 8000ft" />
       </MenuFlyout>
     </AppBarButton.Flyout>
   </AppBarButton>
   <AppBarButton x:Name="groupButton" Icon="List" Label="Group by" />

</StackPanel>

The code for the DataGrid primarily consists of a number or properties and then a DataGridTextColumn for each column added to the control. Here's that code:
<controls:DataGrid
   Grid.Row="1"
     x:Name="dataGrid"
     Margin="12"
     VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
     HorizontalScrollBarVisibility="Visible"
     VerticalScrollBarVisibility="Visible"
     AlternatingRowBackground="Transparent"
     AlternatingRowForeground="Gray"
     AreRowDetailsFrozen="False"
     AreRowGroupHeadersFrozen="True"
     AutoGenerateColumns="False"
     CanUserSortColumns="False"
     CanUserReorderColumns="True"
     CanUserResizeColumns="True"
     ColumnHeaderHeight="32"
     MaxColumnWidth="400"
     FrozenColumnCount="0"
     GridLinesVisibility="None"
     HeadersVisibility="Column"
     IsReadOnly="False"
     RowDetailsTemplate="{StaticResource RowDetailsTemplate}"
     RowDetailsVisibilityMode="Collapsed"
     SelectionMode="Extended"
     RowGroupHeaderPropertyNameAlternative="Range">
   <controls:DataGrid.Columns>
     <controls:DataGridTextColumn Header="Rank" Binding="{Binding Rank}" Tag="Rank" />
     <controls:DataGridTextColumn Header="Mountain" Binding="{Binding Mountain}" Tag="Mountain" />
     <controls:DataGridTextColumn Header="Height (m)" Binding="{Binding Height_m}" Tag="Height_m" />
     <controls:DataGridTextColumn Header="Range" Binding="{Binding Range}" Tag="Range" />
     <controls:DataGridTextColumn Header="Parent Mountain" Binding="{Binding Parent_mountain}" Tag="Parent_mountain" />
   </controls:DataGrid.Columns>

</controls:DataGrid>

For the purposes of a sample app, everything but the grid data is hard coded. Your app could certainly bind any of these properties that you would like to either load from saved configuration or user preferences.
Let's round out our look at the sample app's code by reviewing the DataTemplate for the row details.
<DataTemplate x:Key="RowDetailsTemplate">
   <StackPanel>
     <TextBlock Margin="20" Text="Here are the details for the selected mountain:" />
     <Grid Margin="20,10" Padding="5">
       <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="Auto" />
         <RowDefinition Height="Auto" />
         <RowDefinition Height="*" />
       </Grid.RowDefinitions>
       <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto" />
         <ColumnDefinition Width="Auto" />
       </Grid.ColumnDefinitions>
       <TextBlock Text="Coordinates: " FontWeight="SemiBold" FontSize="13" />
       <TextBlock Grid.Row="1" Text="Prominence (m): " FontWeight="SemiBold" FontSize="13" />
       <TextBlock Grid.Row="2" Text="First Ascent (year): " FontWeight="SemiBold" FontSize="13" />
       <TextBlock Grid.Row="3" Text="No. of ascents: " FontWeight="SemiBold" FontSize="13" />
       <TextBlock Grid.Column="1" FontSize="13" Text="{Binding Coordinates}" HorizontalAlignment="Right" />
       <TextBlock Grid.Row="1" Grid.Column="1" FontSize="13" Text="{Binding Prominence}" HorizontalAlignment="Right" />
       <TextBlock Grid.Row="2" Grid.Column="1" FontSize="13" Text="{Binding First_ascent}" HorizontalAlignment="Right" />
       <TextBlock Grid.Row="3" Grid.Column="1" FontSize="13" Text="{Binding Ascents}" HorizontalAlignment="Right" />
     </Grid>
   </StackPanel>

</DataTemplate>
If a user were to view details on a row, this is how the information would be displayed. The sample app does not appear to currently implement a way to display the RowDetailsTemplate in the UI.

Wrap-Up

Go explore the source code, read the docs and play with the sample app. Then add the DataGrid to your own Windows app! It's a powerful grid control that will save you loads of time.

Happy coding!