【问题标题】:Styling autogenerated DataGrid column on validation failure在验证失败时设置自动生成的 DataGrid 列的样式
【发布时间】:2013-12-05 11:01:26
【问题描述】:

我有一个 DataGrid,其中填充了一个公开 double 类型属性的类的实例。此属性显示在 DataGrid 中。我想实现自定义验证,如果验证失败,我想将整个单元格涂成红色。我想我已经接近让它发挥作用了,但还没有,现在我被难住了。

我的问题是我无法使条件(验证失败)格式化工作。结果是单元格在开始时被正确着色,但是当我插入一个使验证函数返回 false 的值时,我得到了通常的红色边框,白色背景单元格样式。

我应该如何输入这种格式样式?

XAML 代码:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
  <DataGrid x:Name="dg" ItemsSource="{Binding Data}">
    <DataGrid.Resources>
      <ControlTemplate x:Key="validationTemplate">
        <DockPanel>
          <AdornedElementPlaceholder/>
          <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
        </DockPanel>
      </ControlTemplate>

      <Style TargetType="{x:Type TextBox}">
        <Setter Property="Background" Value="Yellow"/>
        <Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}"></Setter>
      </Style>
    </DataGrid.Resources>
  </DataGrid>
</Window>

后面的代码:

public partial class MainWindow : Window
{
  ...

  private void DataGrid_AutoGeneratedColumns(object sender, EventArgs e)
  {
    foreach (DataGridTextColumn c in dg.Columns)
    {
      c.ElementStyle = (Style)dg.FindResource("s");

      for (int i = 0; i < dg.Items.Count; i++)
      {
        DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(i);
        if (row == null) // May be virtualized, bring into view and try again.
        {
          dg.UpdateLayout();
          dg.ScrollIntoView(dg.Items[i]);
          row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(i);
        }
        TextBlock tb = (TextBlock)c.GetCellContent(row);

        Binding binding = BindingOperations.GetBinding(tb, TextBlock.TextProperty);
        binding.ValidationRules.Clear();
        binding.ValidationRules.Add(new VR());
      }
    }
  }
}

public class VR : ValidationRule
{
  public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
  {
    ...
  }
}

编辑:根据开发刺猬的建议更新了 XAML 代码,但仍然无法正常工作。

【问题讨论】:

    标签: c# wpf validation datagrid


    【解决方案1】:

    您似乎错误地使用了 ErrorTemplate。

    看看这个:

    <ControlTemplate x:Key="validationTemplate">
      <DockPanel>
        <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
        <AdornedElementPlaceholder/>
      </DockPanel>
    </ControlTemplate>
    
    
    <TextBox Name="textBox1" Width="50" FontSize="15"
             Validation.ErrorTemplate="{StaticResource validationTemplate}"
             Style="{StaticResource textBoxInError}"
             Grid.Row="1" Grid.Column="1" Margin="2">
      <TextBox.Text>
        <Binding Path="Age" Source="{StaticResource ods}"
                 UpdateSourceTrigger="PropertyChanged" >
          <Binding.ValidationRules>
            <c:AgeRangeRule Min="21" Max="130"/>
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
    

    Validation.ErrorTemplate 将允许您装饰 AdornedElementPlaceholder,在本例中为 TextBox。

    在示例中,我给了你一个红色!将被装饰到 TextBox 的左侧。

    编辑:

    我更改了您的代码以使其正常工作。

    <Grid>
        <DataGrid x:Name="dg" ItemsSource="{Binding Data}" PreparingCellForEdit="OnBeginningEdit">
            <DataGrid.Resources>
                <ControlTemplate x:Key="validationTemplate">
                    <DockPanel>
                        <AdornedElementPlaceholder/>
                        <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
                    </DockPanel>
                </ControlTemplate>
    
                <Style TargetType="{x:Type TextBox}">
                    <Setter Property="Background" Value="Yellow"/>
                    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}"/>
                </Style>
            </DataGrid.Resources>
        </DataGrid>
    </Grid>
    

    这是后面的代码

    public partial class MainWindow : Window
    {
        public List<D> Data { get; set; }
    
        public MainWindow()
        {
            Data = new List<D>();
            Random r = new Random();
            Data.Add(new D(r.NextDouble()));
            Data.Add(new D(r.NextDouble()));
            Data.Add(new D(r.NextDouble()));
    
            InitializeComponent();
    
            DataContext = this;
        }
    
        private void DataGrid_AutoGeneratedColumns(object sender, EventArgs e)
        {
            foreach (DataGridTextColumn c in dg.Columns)
            {
                c.EditingElementStyle = (Style)dg.FindResource("s");
            }
        }
    
        private void OnBeginningEdit(object sender, DataGridPreparingCellForEditEventArgs e)
        {
            TextBox tbx = (TextBox)e.EditingElement;
            Binding binding = BindingOperations.GetBinding(tbx, TextBox.TextProperty);
            binding.ValidationRules.Clear();
            binding.ValidationRules.Add(new VR());
        }
    }
    

    看到你需要使用 TextBoxes,当你在其中写一些东西然后点击离开以触发验证。

    试试看。它对我有用:)

    【讨论】:

    • 这对我没有任何作用。我的列是自动生成的,所以我不确定如何放入 Binding 部分,但是调用了验证代码 - 错误格式是默认格式 - 任何地方都没有红色感叹号。它可能与它是 DataGrid 而不是 TextBox 有关。无论如何,出于这个原因,我也不想附加 TextBlocks,我只想为单元格提供自定义格式。
    • 当单元格不再有效时,您想为单元格提供自定义格式,对吗?好吧,像我向您展示的那样使用 ErrorTemplate,而不是使用 TextBox 类型,因为在我的示例中您应该使用 DataGridCell 类型。我给你的代码是一个例子,而不是你应该复制过去的东西到你的项目中,它就是这样工作的。 :)
    • 目前我正在使用 TextBlock,因为这是我可以在后面的代码中设置的(c.ElementStyle 属性)。我不知道如何将样式应用于单元格,是否在 AdornedElementPlaceholder 中设置样式?我已经尝试过了,但没有成功。就此而言,我无法在验证失败时对我的窗口应用任何类型的自定义更改。它始终只是红色边框。我什至无法摆脱它。
    • 不,您没有在 AdornedElementPlaceholder 上设置样式。您只需定义一个 TargetType DataGridCell 样式并将该样式放在 Window.Resource 中。这就是样式将如何应用于单元格的方式。单元格在生成时会查找样式,它们会找到您将放置在 Window.Resources 中的样式。只要将 Style 的 TargetType 设置为 DataGridCell,它就会自动发生。
    • 我不希望自动应用样式,我希望它在验证失败时发生。我无法在验证失败时提供自定义格式。元素的默认格式,我可以做到。
    猜你喜欢
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    相关资源
    最近更新 更多