I have an WPF MVVM application. In main WPF Window I have a WPF Datagrid Toolkit. This datagrid has some columns. Depending on some conditions (properties bound on view model) a color is applied to the entire row. Additionally there are two special columns. These two columns are of type DataGridTextColumn and are called Date1 and Date2. If Date1 value is greater than Date2 value, Date1 and Date2 cells should be both colored with Orange Red color. Date1 and Date2 which are bound to MyDate1 and MyDate2 view model properties respectively, are of type DateTime.
My problem is: First, when datagrid is loaded with data, rows and Date1 and Date2 columns are colored correctly. Some rows appear with Date1 and Date2 colored with Orange Red color since Date1 > Date2. Then, If I scroll down using vertical scrollbar the datagrid and then I scroll up again to the first datagrid row, I note that now more rows (Date1 and Date2 columns) appear incorrectly colored as Orange Red despite Date1 <= Date2.
What is happening?
View:
<Window x:Name="MainWindow" x:Class="My.Apps.WPF.TestApp.wMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:classes="clr-namespace:My.Apps.WPF.TestApp.Classes"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
WindowState="Maximized">
<Grid x:Name="MyGrid" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<my:DataGrid Grid.Row="1" Name="MyDg"
AutoGenerateColumns="False"
ItemsSource="{Binding Path=MyListOfItems}"
SelectedItem="{Binding Path=MySelectedItem}"
VerticalAlignment="Stretch" IsReadOnly="True"
SelectionMode="Single" ColumnWidth="*"
SelectionChanged="MyDg_SelectionChanged"
Width="{Binding Path=ActualWidth, ElementName=MyGrid}">
<my:DataGrid.Resources>
<classes:BindingProxy x:Key="proxy" Data="{Binding}" />
<Style x:Key="MyDataGridCellStyle" TargetType="{x:Type my:DataGridCell}" BasedOn="{StaticResource {x:Type my:DataGridCell}}">
<!-- If Date1 > Date2 apply background color -->
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource CellDateColorConverter}">
<Binding Path="MyDate1"/> <!-- Date1 value -->
<Binding Path="MyDate2"/> <!-- Date2 value -->
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</my:DataGrid.Resources>
<my:DataGrid.RowStyle>
<!-- Style for entire datagrid row -->
<Style TargetType="my:DataGridRow">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=GroupID, Converter={StaticResource IdGroupConverter}}" Value="True" />
<Condition Binding="{Binding Path=MyFlag}" Value="0" />
<Condition Binding="{Binding Path=StatusFilter, Converter={StaticResource StatusFilterConverter}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#FFAC62"></Setter>
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=MyFlag}}" Value="1">
<Setter Property="Background" Value="{Binding DeniedColor}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=MyFlag}" Value="2">
<Setter Property="Background" Value="{Binding PendingColor}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</my:DataGrid.RowStyle>
<my:DataGrid.Columns>
<my:DataGridTextColumn x:Name="Date1"
CellStyle="{StaticResource MyDataGridCellStyle}"
Binding="{Binding Path=MyDate1, StringFormat=\{0:dd/MM/yyyy\}}"
Header="Date 1"
Width="{Binding DataComandaColWidth, Source={StaticResource DO}, Mode=TwoWay}"
HeaderStyle="{DynamicResource CenterGridHeaderStyle}">
<my:DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Margin" Value="5 0"/>
</Style>
</my:DataGridTextColumn.ElementStyle>
</my:DataGridTextColumn>
<my:DataGridTextColumn x:Name="Date2"
CellStyle="{StaticResource MyDataGridCellStyle}"
Binding="{Binding Path=MyDate2, StringFormat=\{0:dd/MM/yyyy\}}"
Header="Date 2"
Width="auto"
HeaderStyle="{DynamicResource CenterGridHeaderStyle}">
<my:DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Margin" Value="5 0"/>
</Style>
</my:DataGridTextColumn.ElementStyle>
</my:DataGridTextColumn>
</my:DataGrid.Columns>
</my:DataGrid>
</Grid>
</Window>
Classes:
namespace My.Apps.WPF.TestApp.Classes
{
public class CellDateColorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values[0] is DateTime && values[1] is DateTime)
{
DateTime date1 = (DateTime)values[0];
DateTime date2 = (DateTime)values[1];
if (date1.Date > date2.Date)
{
return System.Windows.Media.Brushes.OrangeRed;
}
}
return System.Windows.Data.Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("CellDateColorConverter is a OneWay converter.");
}
}
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
}