在验证失败时为自动生成的DataGrid列设置样式

时间:2013-12-05 11:01:26

标签: c# wpf validation datagrid

我有一个DataGrid,它填充了一个暴露double类型属性的类的实例。此属性显示在DataGrid中。我想实现自定义验证,如果此验证失败,我想将整个单元格着色为红色。我认为我已接近完成它的工作,但尚未完成,现在我很难过。

我的问题是我无法使条件(在验证失败时)格式化工作。结果是单元格在开始时正确着色,但是当我插入一个使得falidating函数返回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)
  {
    ...
  }
}

编辑:根据开发hedgehog的建议更新了XAML代码,但仍无效。

1 个答案:

答案 0 :(得分:2)

您似乎错误地使用了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,当你在其中写一些东西时,然后点击它以触发验证。

试一试。它对我有用:)