Introduction
ASP.NET has provided EmptyDataTemplate
which becomes visible when there are no records to display in DataGrid
. User can expect the same thing from WPF application. But there is no inbuilt support for EmptyDataTemplate
in WPF. As a programmer, we need to handle this requirement a bit differently. This article provides you with a hint to add EmptyDataTemplate
for DataGrid
.
Background
WPF provides the ability to apply/change the ControlTemplate
for its Templated Controls. DataGrid
does have the ControlTemplate
which we can use to add EmptyDataTemplate
in the DataGrid
.
Using the Code
We want our EmptyDataTemplate
to be available for DataGrid
without making any change in the existing DataGrid
control's code and it should be configurable, i.e., user should be able to use it optionally.
Add a class EmptyDataTemplateService
, which will contain an attached dependency property of type DataTemplate
.
public class EmptyDataTemplateService
{
public static readonly DependencyProperty EmptyDataTemplateProperty =
DependencyProperty.RegisterAttached("EmptyDataTemplate",
typeof(DataTemplate), typeof(EmptyDataTemplateService), null);
public static DataTemplate GetEmptyDataTemplate(DataGrid grid)
{
return grid.GetValue(EmptyDataTemplateService.EmptyDataTemplateProperty) as DataTemplate;
}
public static void SetEmptyDataTemplate(DataGrid grid, DataTemplate emptyDataTemplate)
{
grid.SetValue(EmptyDataTemplateService.EmptyDataTemplateProperty, emptyDataTemplate) ;
}
}
Now we have the EmptyDataTemplate
attached property to use inside DataGrid
. We can now use this property in DataGrid
template. We have added ContentControl
above "RowsPresenter
" in the following XAML.
<ControlTemplate TargetType="local:DataGrid">
<Grid>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="DisabledVisualElement"
Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="2">
<Grid Name="Root" Background="{TemplateBinding Background}">
<Grid.Resources>
<ControlTemplate x:Key="TopLeftHeaderTemplate"
TargetType="localprimitives:DataGridColumnHeader">
<Grid Name="Root">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border BorderThickness="0,0,1,0"
BorderBrush="#FFC9CACA" Background="#FF1F3B53" Grid.RowSpan="2">
<Rectangle Stretch="Fill" StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint=".7,0" EndPoint=".7,1">
<GradientStop Color="#FCFFFFFF" Offset="0.015" />
<GradientStop Color="#F7FFFFFF" Offset="0.375" />
<GradientStop Color="#E5FFFFFF" Offset="0.6" />
<GradientStop Color="#D1FFFFFF" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
<Rectangle VerticalAlignment="Bottom" Width="Auto"
StrokeThickness="1" Height="1" Fill="#FFDBDCDC"
Grid.RowSpan="2"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="TopRightHeaderTemplate"
TargetType="localprimitives:DataGridColumnHeader">
<Grid Name="RootElement">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border BorderThickness="1,0,0,0"
BorderBrush="#FFC9CACA" Background="#FF1F3B53" Grid.RowSpan="2">
<Rectangle Stretch="Fill">
<Rectangle.Fill>
<LinearGradientBrush StartPoint=".7,0" EndPoint=".7,1">
<GradientStop Color="#FCFFFFFF" Offset="0.015" />
<GradientStop Color="#F7FFFFFF" Offset="0.375" />
<GradientStop Color="#E5FFFFFF" Offset="0.6" />
<GradientStop Color="#D1FFFFFF" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
</Grid>
</ControlTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<localprimitives:DataGridColumnHeader Name="TopLeftCornerHeader"
Template="{StaticResource TopLeftHeaderTemplate}" Width="22" />
<localprimitives:DataGridColumnHeadersPresenter
Name="ColumnHeadersPresenter" Grid.Column="1"/>
<localprimitives:DataGridColumnHeader Name="TopRightCornerHeader"
Grid.Column="2" Template="{StaticResource TopRightHeaderTemplate}" />
<Rectangle Name="ColumnHeadersAndRowsSeparator"
Grid.ColumnSpan="3" VerticalAlignment="Bottom"
Width="Auto" StrokeThickness="1"
Height="1" Fill="#FFC9CACA"/>
<ContentControl Grid.ColumnSpan="2" Grid.Row="1"
Visibility="{Binding Path=ItemsSource.Count,
Converter={StaticResource CountToVisibilityConverter}}"
ContentTemplate="{Binding Path=(local:EmptyDataTemplateService.EmptyDataTemplate),
RelativeSource={RelativeSource TemplatedParent}}"
HorizontalAlignment="Streach" HorizontalContentAlignment="Streach"/>
<localprimitives:DataGridRowsPresenter Name="RowsPresenter"
Grid.ColumnSpan="2" Grid.Row="2" />
<Rectangle Name="BottomRightCorner" Fill="#FFE9EEF4"
Grid.Column="2" Grid.Row="3" />
<Rectangle Name="BottomLeftCorner" Fill="#FFE9EEF4"
Grid.Row="3" Grid.ColumnSpan="2" />
<ScrollBar Name="VerticalScrollbar" Orientation="Vertical"
Grid.Column="2" Grid.Row="2" Width="18" Margin="0,-1,-1,-1"/>
<Grid Grid.Column="1" Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Name="FrozenColumnScrollBarSpacer" />
<ScrollBar Name="HorizontalScrollbar" Grid.Column="1"
Orientation="Horizontal" Height="18" Margin="-1,0,-1,-1"/>
</Grid>
<dataInput:ValidationSummary Name="ValidationSummary"
Grid.Row="4" Grid.ColumnSpan="3" MaxHeight="90"/>
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" IsHitTestVisible="False"
Height="Auto" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Width="Auto" CornerRadius="2"
Background="#8CFFFFFF" Opacity="0"/>
</Grid>
</ControlTemplate>
This sets the EmptyDataTemplate
in your project. To use the EmptyDataTemplate
, you can use following code inside DataGrid
as:
<DataGrid>
<local:EmptyDataTemplateService.EmptyDataTemplate>
<DataTemplate>
<TextBlock Text="Records not found."/>
</DataTemplate>
</local:EmptyDataTemplateService.EmptyDataTemplate>
</DataGrid>
Points of Interest
In this way, you can add custom sections to DataGrid
such as footer.