2014-04-04 73 views
0

我們研究了使用wpf datagrid的開箱驗證,但發現它並沒有給我們足夠的驗證工作方式的控制權。也就是說,我們不希望某個字段在用戶單擊保存按鈕或編輯該字段之前顯示爲無效。我們可以通過一個我們很滿意的解決方案將它與文本框和複選框一起使用。只要我們可以訪問行綁定的對象,我們相信它可以用於datagrdi。但是,我們無法通過綁定來獲取對象。WPF DataGrid和綁定到行數據上下文

我附上了代碼的相關部分以重現樣本。 ValidationContext類的ObjectToValidate屬性是我們希望將行對象綁定到的對象。如果你連接下面的代碼,運行它,然後編輯Name列中的一個單元格,你將在PropertyValidation類的ValidateMethod中得到異常。

窗口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類

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類

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

究竟什麼是你遇到的問題? – Greg

+0

我們遇到了使用開箱驗證的問題,因爲這些字段在我們準備好之前會進行驗證。我們已經修復了除網格以外的所有內容。它也讓我們更細緻地控制驗證發生的時間和方式。將它綁在網格上是我們唯一留下的東西,如果我可以訪問該行所綁定的對象,那麼在這種情況下,我們的模型就沒問題了。 – CodeHulk

+0

我試圖解決同樣的問題,並以非常類似的解決方案結束。問題是當調用Validate時,我的代碼的'Context'等價物總是'null'。我該如何解決?你有沒有得到它的工作? – Linus

回答

0

很難發現這一點,但它僅僅是個結合:

<behaviors:ValidationContext ObjectToValidate="{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> 
+0

感謝回覆喬希,但這仍然不適合我。該對象仍然返回爲空。我會盡量讓今天發佈更多代碼。 – CodeHulk

+0

我已更新我的代碼示例以包含所有必要的部分。 – CodeHulk