WPF DataGrid和绑定到行数据上下文

时间:2014-04-04 18:03:55

标签: c# wpf datagrid

我们研究了使用wpf datagrid的开箱即用验证,但发现它没有给我们足够的控制验证的工作方式。即,在用户单击“保存”按钮或编辑该字段之前,我们不希望字段显示为无效。我们能够通过文本框和复选框使用我们满意的解决方案。我们相信它只适用于datagrdi,只要我们可以访问行绑定的对象。但是,我们无法通过绑定来获取对象。

我已附上代码的相关部分以重现样本。 ValidationContext类上的ObjectToValidate属性是我们想要将行对象绑定到的属性。如果你连线下面的代码运行它,然后编辑Name列中的一个单元格,你将在PropertyValidation类的ValidateMethod中获得异常。

Window XAML

<Window x:Class="DataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow">
    <DataGrid ItemsSource="{Binding MyItems}" IsReadOnly="{Binding IsReadOnly}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name">
                <DataGridTextColumn.Binding>
                    <Binding Path="Name" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
                        <Binding.ValidationRules>
                            <behaviors:PropertyValidation PropertyName="Name">
                                <behaviors:PropertyValidation.Context>
                                    <behaviors:ValidationContext ObjectToValidate="{Binding}"/>
                                </behaviors:PropertyValidation.Context>
                            </behaviors:PropertyValidation>
                        </Binding.ValidationRules>
                    </Binding>
                </DataGridTextColumn.Binding>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

Windows代码背后

public partial class MainWindow : Window
{
    public ObservableCollection<MyItem> MyItems { get; set; }

    public MainWindow()
    {
        InitializeMyItems();
        InitializeComponent();
        DataContext = this;
    }

    private void InitializeMyItems()
    {
        MyItems = new ObservableCollection<MyItem>();

        for (int i = 0; i < 10; i++)
        {
            MyItems.Add(new MyItem() { Age = i, Name = "Name" + i.ToString() });
        }
    }
}

PropertyValidation Class

public class PropertyValidation : ValidationRule
{
    public string PropertyName { get; set; }
    public ValidationContext Context { get; set; }
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (Context.ObjectToValidate == null) throw new Exception("The validation object is null.");

        return new ValidationResult(true, "");
    }
}

ValidationContext Class

public class ValidationContext : DependencyObject
{

    public object ObjectToValidate
    {
        get { return (object)GetValue(ObjectToValidateProperty); }
        set { SetValue(ObjectToValidateProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ObjectToValidate.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ObjectToValidateProperty =
        DependencyProperty.Register("ObjectToValidate", typeof(object), typeof(ValidationContext), new PropertyMetadata(null));
}

1 个答案:

答案 0 :(得分:0)

很难找到这个,但它只是绑定:

<behaviors:ValidationContext ObjectToValidate="{Binding}"/>

{Binding}通常表示在某一行绑定的对象。

修改

您可以在MyItem类上使用IDataErrorInfo接口吗?

public class MyItem : IDataErrorInfo
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public string Error
        {
            get
            {
                return null;
            }
        }

        public string this[string name]
        {
            get
            {
                string result = null;

                if (name == "Name")
                {
                    if (string.IsNullOrEmpty(Name))
                    {
                        result = "Name must be specified.";
                    }
                }
                return result;
            }
        }
    }

然后XAML看起来像这样:

<DataGrid ItemsSource="{Binding MyItems}" IsReadOnly="{Binding IsReadOnly}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name">
                <DataGridTextColumn.Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
                    <DataGridTextColumn.Binding.ValidationRules>
                        <DataErrorValidationRule/>
                   </DataGridTextColumn.Binding.ValidationRules>
               </DataGridTextColumn.Binding>
            </DataGridTextColumn>
          </DataGrid.Columns>
 </DataGrid>