I implemented the classes UtilityElectricityConsumptionModel
and UtilityNaturalGasConsumptionModel
from the abstract class UtilityConsumptionModel
. The UtilityNaturalGasConsumptionModel
just has the extra ConversionCoefficient
property added.
I bind to ConversionCoefficient
in a DataGrid
via the DataGridTemplateColumn
and Trigger
. I don't get any binding failure initially, but I get binding failures since I begin scrolling the DataGrid
. Is there a way to avoid these binding failures?
<!-- Conversion Coefficient -->
<DataGridTemplateColumn Width="100" Header="Conversion Coefficient">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Background" Value="{StaticResource PrimarySolidColorBrush}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Source}" Value="{x:Static models:UtilitySource.NaturalGas}">
<Setter Property="Padding" Value="2,0,2,0" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Text" Value="{Binding ConversionCoefficient, StringFormat='0.00'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
After testing the "quick mock" in my other post, it occurred to me that there is an improved approach that might answer your question:
Is there a way to avoid these binding failures?
Use a DataTemplateSelector
in place of the DataTrigger
stategy.
public class UtilityConsumptionTemplateSelector : DataTemplateSelector
{
public DataTemplate? ElectricityTemplate { get; set; }
public DataTemplate? NaturalGasTemplate { get; set; }
public override DataTemplate? SelectTemplate(object item, DependencyObject container)
{
if (item is UtilityElectricityConsumptionModel)
{
return ElectricityTemplate;
}
if (item is UtilityNaturalGasConsumptionModel)
{
return NaturalGasTemplate;
}
return base.SelectTemplate(item, container);
}
}
<Window x:Class="abstract_class_binding_issue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:abstract_class_binding_issue"
xmlns:models="clr-namespace:abstract_class_binding_issue.Models"
mc:Ignorable="d"
Title="MainWindow" Height="250" Width="400">
<Window.Resources>
<SolidColorBrush x:Key="PrimarySolidColorBrush" Color="LightGray"/>
<DataTemplate x:Key="ElectricityTemplate">
<TextBlock Text="Electricity" Background="{StaticResource PrimarySolidColorBrush}" HorizontalAlignment="Center"/>
</DataTemplate>
<DataTemplate x:Key="NaturalGasTemplate">
<TextBlock Text="{Binding ConversionCoefficient, StringFormat='0.00'}"
Background="Transparent" HorizontalAlignment="Right" Padding="2,0,2,0"/>
</DataTemplate>
<local:UtilityConsumptionTemplateSelector
x:Key="UtilityTemplateSelector"
ElectricityTemplate="{StaticResource ElectricityTemplate}"
NaturalGasTemplate="{StaticResource NaturalGasTemplate}" />
</Window.Resources>
<Window.DataContext>
<models:MainViewModel/>
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding UtilityConsumptions}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Width="100" Header="Conversion Coefficient"
CellTemplateSelector="{StaticResource UtilityTemplateSelector}" />
<DataGridTextColumn Header="Utility Type" Binding="{Binding Source}" Width="200"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>