2010-07-20 102 views
1

我今天遇到了一個問題,其中有一個BindingGroup,它有多個ValidationRules同時失敗。問題是,當我嘗試並確定是否有任何錯誤(即將CanExecute設置爲false)時,ArgumentExceptionBindingGroup.ValidateWithoutUpdate冒出來。BindingGroup with multiple(failing)ValidationRules

我已經成功地提煉出它在下面的例子(對不起,它仍然跨越多個數據源,但我已經封閉,應該是拷貝/ pasteable到一個新的WPF項目的所有相關部分):

窗口1的.xaml:

<Window 
    x:Class="BindingGroupTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:l="clr-namespace:BindingGroupTest" 
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" 
    Title="Window1" Height="300" Width="300"> 

    <Window.BindingGroup> 
     <BindingGroup Name="RootBindingGroup"> 
      <BindingGroup.ValidationRules> 
       <l:TestRule1 /> 
       <l:TestRule2 /> 
      </BindingGroup.ValidationRules> 
     </BindingGroup> 
    </Window.BindingGroup> 

    <StackPanel> 
     <TextBox Text="{Binding 
      Path=Name, 
      BindingGroupName=RootBindingGroup, 
      UpdateSourceTrigger=PropertyChanged, 
      diag:PresentationTraceSources.TraceLevel=High}" /> 
     <TextBox Text="{Binding 
      Path=Age, 
      BindingGroupName=RootBindingGroup, 
      UpdateSourceTrigger=PropertyChanged, 
      diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Button Content="Validate" Click="DoValidate" /> 
    </StackPanel> 
</Window> 

Window1.xaml.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace BindingGroupTest 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      this.DataContext = new Person() 
      { 
       Name="Test", 
       Age=30, 
      }; 

      InitializeComponent(); 

      this.BindingGroup.BeginEdit(); 
     } 

     private void DoValidate(object sender, RoutedEventArgs e) 
     { 
      try 
      { 
       if (!this.BindingGroup.ValidateWithoutUpdate()) 
        MessageBox.Show("Validation failed!"); 
       else 
        MessageBox.Show("Validation passed!"); 
      } 
      catch (Exception ex) 
      { 
       var msg = "While validating, caught exception: " + ex.Message; 
       MessageBox.Show(msg); 
      } 
     } 
    } 
} 

Person.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace BindingGroupTest 
{ 
    public class Person 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
    } 
} 

TestRule1.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace BindingGroupTest 
{ 
    public class TestRule1 : ValidationRule 
    { 
     public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
     { 
      var p = ((BindingGroup)value).Items[0] as Person; 
      if (p == null) 
       return ValidationResult.ValidResult; 

      if (p.Age < 0) 
       return new ValidationResult(false, "Surely, you've been born yet!"); 

      return ValidationResult.ValidResult; 
     } 
    } 
} 

TestRule2.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace BindingGroupTest 
{ 
    public class TestRule2 : ValidationRule 
    { 
     public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
     { 
      var p = ((BindingGroup)value).Items[0] as Person; 
      if (p == null) 
       return ValidationResult.ValidResult; 

      if (string.IsNullOrEmpty(p.Name)) 
       return new ValidationResult(false, "What, no name?"); 

      return ValidationResult.ValidResult; 
     } 
    } 
} 

基本上,我的問題是,如果兩個TestRule1和TestRule2 fail, I get an ArgumentException的bubbling up when I call this.BindingGroup.ValidateWithoutUpdate()with message "Cannot have duplicates in this Collection", parameter name: "validationError". I dug around through the implementation of BindingGroup , and it seems that it is using itself as the second parameter to ValidationError , which is the bindingInError parameter, which the underlying ValidationErrorCollection`必須是唯一的。

不可否認,這個例子很有意思,但它完美地證明了我的現實世界中沒有的問題。 (我有2個完全獨立的ValidationRule s,它們在同一個業務對象的不同屬性上運行,並且將它們合併爲一個單一的ValidationRule)將毫無意義。此外,我可以找到的使用BindingGroup的每個示例都只能演示使用單個ValidationRule,但構造明確支持並接受多個規則,儘管顯然只要一次只有一個失敗。

我做錯了什麼,或者這似乎是BindingGroup實施中的一個錯誤,因爲我目前傾向於認爲。

對於它的價值,我使用VS2008和.Net 3.5 SP1。

+0

對不起,我不確定爲什麼,但儘管顯示在編輯窗口中,Window1.xaml中窗口聲明的頂部並未顯示在代碼中。唯一要注意的是名稱空間'l'被定義爲「clr-namespace:BindingGroupTest」。 – 2010-07-20 00:48:32

+0

解決了你的問題。您沒有使用代碼按鈕,代碼突出顯示,因此無法正常工作。 – Femaref 2010-07-20 00:56:38

+0

啊,謝謝你,@Femaref。 – 2010-07-20 01:04:48

回答

2

如果你在.NET 4.0中運行它,它會以你期望的方式工作,所以它看起來確實是一個bug,並且在下一個版本中已經修復。

+0

謝謝。很高興知道我不會精神崩潰,並且它固定在4.0。我已經通過將調用包裝到'BindingGroup.ValidateWithoutUpdate()'來捕獲ArgumentException並將其視爲未通過驗證。討厭,但可行,直到我被允許遷移到4.0。 – 2010-07-21 18:44:18