代码之家  ›  专栏  ›  技术社区  ›  joerage

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

  •  5
  • joerage  · 技术社区  · 15 年前

    当出现验证错误时,我尝试更改DataGridCell的默认样式(在wpftoolkit DataGrid中)。默认为红色边框。如何放置自己的模板?

    谢谢。

    2 回复  |  直到 15 年前
        1
  •  10
  •   Jorge Navarrete    12 年前

    试试这个:

    <!-- 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>
    
        2
  •  2
  •   BalusC    13 年前

    有一个 nice tutorial

        3
  •  1
  •   pyzon    4 年前

    验证错误似乎永远不会到达列的ElementStyle或CellStyle内部。我怀疑这是因为它达到并可以在列的EditingElementStyle和datagrid的RowStyle中使用。

    <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.error模板也:

    <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上相同。这两种方法都不能真正解决问题:更改行样式显然不能显示错误所在的单元格,而且一旦文本框散焦,编辑样式就不可见。

    this tutorial 在展示了一个设置验证.HasErrorEditingElementStyle上的触发样式:

    列使用的单元格样式。

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

    在这个例子中,有一些产品,它们有一个类别,它将显示在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>
    

    以下是产品类别:

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