具有验证错误样式的WPF Datagrid单元格

时间:2010-03-13 19:59:55

标签: wpf validation datagrid wpftoolkit datagridcell

我正在尝试在出现验证错误时更改DataGridCell的默认样式(在WPF Toolkit DataGrid中)。默认为红色边框。我怎样才能放置自己的模板?

感谢。

3 个答案:

答案 0 :(得分:9)

试试这个:

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

答案 1 :(得分:2)

Diederik Krols有一个nice tutorial,它完全符合您对WPF Toolkit DataGrid的要求。

答案 2 :(得分:0)

下面是一种解决方案,但首先,让我分享我的发现。

似乎验证错误从未到达列的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上不起作用。我倾向于相信这是一个错误,因为在this tutorial中,它显示了在示例中设置Validation.HasError触发的样式,并显示在EditingElementStyle上:

您可以通过替换以下内容来实现更广泛的自定义 列使用的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>

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

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