WPF数据表格单元格的验证错误样式

5
我想要更改DataGridCell(WPF Toolkit DataGrid中的单元格)在验证错误时的默认样式,它默认为红色边框。请问我如何使用自己的模板?
谢谢。
3个回答

10

试试这个:

<!-- 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>

这仅在单元格正在编辑时起作用。然后默认的错误样式会被恢复。如果这是预期的效果,则应将标题更改为类似于“WPF Datagrid Cell,Editing Validation Error Style”的内容。如果这不是预期的效果,则此答案不完整。 - AgostinoX

2

这里有一篇来自Diederik Krols的不错的教程,它能够完全满足你对WPF Toolkit DataGrid的要求。


4
这实际上并没有涉及单元格的验证,它只涉及行的验证... 我们仍在寻找一种覆盖红色轮廓行为的方法,例如:改为使用黄色背景... - Jay
真的吗,甚至是在“行验证”部分之前的“单元格验证”部分? - PandaWood
3
我指的是单元格的“样式”。文章描述了如何验证值,但没有更改单元格样式,比如将其改为黄色背景而不是标准的红色边框,这是最初的问题。它验证了单元格的值,但然后只修改了行样式。我找到了一个网址,可以部分解决修改实际单元格的问题:http://msdn.microsoft.com/en-us/library/ee622975.aspx。 - Jay

1
以下是一种解决方案,但首先让我分享一下我的发现。
似乎验证错误永远不会到达列的ElementStyle或CellStyle。我怀疑这是因为它可以到达并且可以在列的EditingElementStyle和datagrid的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>

两种方法都可以正常工作。编辑元素样式也是一样。但是这两种方法都不能解决问题:更改行样式显然不能显示出错误所在的单元格,而编辑样式一旦文本框失去焦点就不可见了。

不幸的是,由于某些原因,同样的方法在ElementStyle或CellStyle上不起作用。我倾向于认为这是一个bug,因为在this tutorial中,在展示设置Validation.HasError触发样式在EditingElementStyle上的示例后,它说:

您可以通过替换列使用的CellStyle来实现更广泛的自定义。

解决方案

一种解决方法是不使用触发器,而是将单元格的背景(或任何样式属性)绑定到数据对象的新属性上。我会展示我的意思。

在这个例子中,有产品,它们有一个类别,将在datagrid中显示为文本列。以下是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>

以下是Product类的代码:

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));
    }
}

很明显,这种解决方案的巨大缺点是需要为数据对象中的每个属性设置一个(或多个,如果您想要更复杂的样式)样式属性,并且需要大量手动设置这些属性。但它仍然是一种解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接