2010-07-20 104 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