具有多个(失败)ValidationRules 的 BindingGroup
我今天在工作中遇到了一个问题,其中我有一个 BindingGroup
,它有多个同时失败的 ValidationRule
。问题是,当我尝试确定是否存在任何错误(即设置 CanExecuteArgumentException
从 BindingGroup.ValidateWithoutUpdate
> 在命令false
上)。
我已设法将其提炼为以下示例(抱歉,它仍然跨越多个源,但我已将所有应复制/粘贴到新 WPF 项目中的相关部分包含在内):
Window1.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都失败,我会得到一个
ArgumentException冒泡我调用
this.BindingGroup.ValidateWithoutUpdate()并显示消息“此集合中不能有重复项”,参数名称:“validationError”。我仔细研究了
BindingGroup的实现,似乎它使用自身作为
ValidationError的第二个参数,即
bindingInError参数,底层的 ValidationErrorCollection` 要求是唯一的。
诚然,这个例子是人为的,但是,它完美地展示了我的现实世界问题,但事实并非如此。 (我有 2 个完全独立的 ValidationRule
,它们对同一业务对象的不同属性进行操作,将它们折叠成一个 ValidationRule
毫无意义) 。此外,我能找到的使用 BindingGroup
的每个示例都仅演示了单个 ValidationRule
的使用,但该构造显然支持并接受多个规则,尽管显然,只要一次只有一个失败。
我是否做错了什么,或者这似乎是 BindingGroup
实现中的一个错误,正如我目前倾向于认为的那样。
无论如何,我使用的是 VS2008 和 .Net 3.5 SP1。
I ran into a problem today at work wherein I have a BindingGroup
that has multiple ValidationRule
s that are failing simultaneously. Problem is, I get an ArgumentException
bubbling up from withing BindingGroup.ValidateWithoutUpdate
when I try and determine if there are any errors (i.e. to set the CanExecute
on a command to false
).
I've managed to distill it to the following example (sorry, it still crosses multiple sources, but I've enclosed all relevant parts that should be copy/pasteable into a new WPF project):
Window1.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;
}
}
}
Basically, my problem is that if both TestRule1
and TestRule2fail, I get an
ArgumentExceptionbubbling 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
bindingInErrorparameter, which the underlying
ValidationErrorCollection` requires to be unique.
Admittedly, this example is contrived, however, it perfectly demonstrates my real-world issue that is not. (I have 2, entirely independent, ValidationRule
s that are operating on different attributes of the same business object, and it would make zero sense to collapse these into a single ValidationRule
). Additionally, every example I can find of using BindingGroup
only ever demonstrates use of a single ValidationRule
, but the construct clearly supports and accepts multiple rules, albeit, apparently, so long as only a single fails at a time.
Am I doing something wrong, or does this appear to be a bug in the BindingGroup
implementation, as I'm inclined to think currently.
For what it's worth, I'm using VS2008 with .Net 3.5 SP1.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您在 .NET 4.0 中运行它,它将按照您期望的方式工作,因此看起来它确实是一个错误,并且已在下一个版本中修复。
It will work the way you expect if you run it in .NET 4.0, so it looks like it was indeed a bug and has been fixed in the next release.