I'm trying to change the way a DataGridCell appears when it has error content. By default, it has a white background and a red border when it encounters an error. However, it seems that my attempts to set the Validation.ErrorTemplate of this class are being ignored, as are my Triggers on the Validation.HasError property. All of the code necessary to reproduce the problem is located below; I have been completely unable to get WPF to apply any kind of stylings to the cell on error. Does anyone see the problem here or have a potential workaround?
APP.XAML
<Application.Resources>
<ControlTemplate x:Key="ErrorTemplate">
<DockPanel>
<TextBlock Text="Busted!"/>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
<Style x:Key="{x:Type WpfToolkit:DataGridCell}" TargetType="{x:Type WpfToolkit:DataGridCell}">
<Style.Setters>
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}"/>
<Setter Property="Background" Value="Green"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip" Value="Doh!"/>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
MainWindow.xaml
<Grid>
<WpfToolkit:DataGrid ItemsSource="{Binding Path=MyItems, ValidatesOnDataErrors=True}" AutoGenerateColumns="False">
<WpfToolkit:DataGrid.Columns>
<WpfToolkit:DataGridTextColumn Header="Wheel Count" Binding="{Binding WheelCount, ValidatesOnDataErrors=True}"/>
<WpfToolkit:DataGridTextColumn Header="Car Colour" Binding="{Binding Color, ValidatesOnDataErrors=True}"/>
</WpfToolkit:DataGrid.Columns>
</WpfToolkit:DataGrid>
</Grid>
The class being bound to is
Car.cs
class Car : IDataErrorInfo, INotifyPropertyChanged
{
public Car(int numWheels, string Color)
{
_color = Color;
_wheelCount = numWheels;
}
private string _color;
public string Color
{
get
{
return _color;
}
set
{
_color = value;
if (value.Length > 10)
{
//Warning
}
if (value.Length > 20)
{
//Error
}
PropChanged("Color");
}
}
private int _wheelCount;
public int WheelCount
{
get
{
return _wheelCount;
}
set
{
_wheelCount = value;
if (value != 4)
{
AddError("WheelCount", "There should be 4 wheels on the car!");
}
else
this.ClearError("WheelCount");
PropChanged("WheelCount");
}
}
public void AddError(string propName, string errorMessage)
{
if (myErrors.ContainsKey(propName))
myErrors.Remove(propName);
myErrors.Add(propName, errorMessage);
PropChanged(propName);
PropChanged("Error");
}
public void ClearError(string propName)
{
if (myErrors.ContainsKey(propName))
myErrors.Remove(propName);
}
private Dictionary<string, string> myErrors = new Dictionary<string, string>();
public string Error
{
get
{
StringBuilder myError = new StringBuilder("Errors");
foreach (KeyValuePair<string,string> currentErr in myErrors)
{
myError.AppendLine(currentErr.Key + ":" + currentErr.Value);
}
return myError.ToString();
}
}
public string this[string columnName]
{
get
{
if (!myErrors.ContainsKey(columnName))
return null;
else
return myErrors[columnName];
}
}
public void PropChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
The "ViewModel" for the view is CarVM:
CarVM.cs
class CarVM
{
public CarVM()
{
for (int currentCar = 0; currentCar < 20; currentCar++)
{
myCars.Add(new Car(4, "Red"));
}
MyItems = (CollectionView)CollectionViewSource.GetDefaultView(myCars);
}
private List<Car> myCars = new List<Car>();
public CollectionView MyItems
{
get;
private set;
}
}
And the code in the window is very simple:
MainWindow.Xaml.Cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new CarVM();
}
}