【问题标题】:WPF Datagrid Cell with Validation Error Style具有验证错误样式的 WPF Datagrid 单元格
【发布时间】:2011-01-27 05:52:06
【问题描述】:

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

谢谢。

【问题讨论】:

    标签: wpf validation datagrid wpftoolkit datagridcell


    【解决方案1】:

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

    验证错误似乎永远不会到达列的 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 中,它在展示了在 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>
    

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

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

    【讨论】:

      【解决方案2】:

      试试这个:

      <!-- 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,编辑验证错误样式”之类的内容。如果这不是预期的效果,那么这个答案是不完整的。
      【解决方案3】:

      有一个来自 Diederik Krols 的 nice tutorial 完全符合您对 WPF 工具包 DataGrid 的要求。

      【讨论】:

      • 这实际上并没有解决单元格的验证问题,它解决了行的验证问题...仍在寻找一种方法来覆盖红色轮廓行为,例如:改用黄色背景...
      • 真的,即使是在“行验证”部分之前的“单元验证”部分?
      • 我的意思是单元格的“样式”。本文描述了如何验证值,但不更改单元格样式,例如,将单元格样式更改为黄色背景而不是标准的红色边框,这是最初的问题。它验证单元格值,但只修改行样式。我发现这是修改实际单元格的地址类型:msdn.microsoft.com/en-us/library/ee622975.aspx
      猜你喜欢
      • 2011-05-12
      • 2011-06-29
      • 2016-04-28
      • 1970-01-01
      • 2014-08-08
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多