当出现验证错误时,我正在尝试更改 DataGridCell 的默认样式(在 WPF Toolkit DataGrid 中)。默认为红色边框。如何放置自己的模板?
谢谢。
当出现验证错误时,我正在尝试更改 DataGridCell 的默认样式(在 WPF Toolkit DataGrid 中)。默认为红色边框。如何放置自己的模板?
谢谢。
尝试这个:
<!-- Cell Style -->
<Style x:Key="CellErrorStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
并使用它:
<DataGrid.Columns>
<DataGridTextColumn
ElementStyle="{StaticResource CellErrorStyle}">
</DataGridTextColumn>
</DataGrid.Columns>
Diederik Krols 提供了一个很好的教程,它完全符合您对 WPF Toolkit DataGrid 的要求。
下面是一种解决方案,但首先,让我分享一下我的发现。
似乎验证错误永远不会到达列的 ElementStyle 或 CellStyle 内。我怀疑这是因为它到达并且可以在列的 EditingElementStyle 和数据网格的 RowStyle 中使用。
例如,您可以根据 Validation.HasError 设置样式:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
或者您也可以设置 Validation.ErrorTemplate:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="3">
<AdornedElementPlaceholder />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
两者都工作得很好。在 EditingElementStyle 上也是如此。这些都没有真正解决问题:更改行样式显然不会显示错误所在的单元格,并且一旦文本框散焦,编辑样式就不可见。
不幸的是,由于某种原因,相同的方法不适用于 ElementStyle 或 CellStyle。我倾向于认为这是一个错误,因为在本教程中,它在展示了在 EditingElementStyle 上设置 Validation.HasError 触发样式的示例之后说:
您可以通过替换列使用的 CellStyle 来实现更广泛的自定义。
一种解决方法是不使用触发器,而是将单元格的背景(或您想要的任何样式属性)绑定到数据对象的新属性。我会表明我的意思。
在此示例中,有产品,它们有一个类别,将显示在数据网格的文本列中。这是 XAML:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Products}">
<DataGrid.Columns>
<!-- other columns -->
<DataGridTextColumn Header="Category">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background"
Value="{Binding Mode=OneWay, Path=CategoryErrorBackgroundColor}" />
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.Binding>
<Binding Path="Category" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<!-- other columns -->
</DataGrid.Columns>
</DataGrid>
这是产品类:
public class Product : INotifyPropertyChanged
{
// ...other fields and properties
private string category;
private SolidColorBrush categoryErrorBackgroundColor;
public string Category
{
get
{
return category;
}
set
{
// validation checks
if (value.Lenght < 5)
{
CategoryErrorBackgroundColor = Brushes.Red;
// Notice that throwing is not even necessary for this solution to work
throw new ArgumentException("Category cannot be shorter than 5 characters.");
}
else
{
CategoryErrorBackgroundColor = Brushes.Transparent;
}
category = value;
}
}
// This is the property I'm binding to the cell's background
// It has to have the appropriate type
public SolidColorBrush CategoryErrorBackgroundColor
{
get
{
return categoryErrorBackgroundColor;
}
set
{
categoryErrorBackgroundColor = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
显然,这种解决方案的巨大缺点是它需要为数据对象中的每个属性提供一个(或多个,如果您想要更复杂的样式)样式属性,并且需要对这些属性进行大量手动设置。但这仍然是一种解决方案。