这是我尝试使用BindingGroup的一些代码的(有些)减少的例子:
XAML:
<Window x:Class="BindingGroupQuandary.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingGroupQuandary"
Title="Binding Group Test" Width="400" Height="400" MinWidth="400" MinHeight="400">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<GroupBox Header="Items">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Name="dataList">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="First Property" DisplayMemberBinding="{Binding FirstProperty}" />
<GridViewColumn Header="Second Property" DisplayMemberBinding="{Binding SecondProperty}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Button Grid.Row="1" Content="Add Item" Click="add_Click" HorizontalAlignment="Left" Margin="0,5,0,5" />
</Grid>
</GroupBox>
<GroupBox Grid.Row="1" Name="editControls" Header="Edit Item">
<GroupBox.BindingGroup>
<BindingGroup Name="editItemBindings"/>
</GroupBox.BindingGroup>
<StackPanel>
<Label Content="First Property (Required)"/>
<TextBox>
<TextBox.Text>
<Binding Path="FirstProperty">
<Binding.ValidationRules>
<local:NotEmptyValidationRule ValidationStep="RawProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Label Content="Second Property (Required)"/>
<TextBox>
<TextBox.Text>
<Binding Path="SecondProperty">
<Binding.ValidationRules>
<local:NotEmptyValidationRule ValidationStep="RawProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="Commit" Click="commit_Click" HorizontalAlignment="Left" Margin="0,10,0,0"/>
</StackPanel>
</GroupBox>
</Grid>
</Window>
代码隐藏:
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
namespace BindingGroupQuandary
{
class SomeData
{
public string FirstProperty { get; set; }
public string SecondProperty { get; set; }
}
class NotEmptyValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string textValue = (value as string);
ValidationResult result;
if (string.IsNullOrWhiteSpace(textValue))
{
result = new ValidationResult(false, "The field must contain a text value and cannot be empty.");
}
else
{
result = new ValidationResult(true, null);
}
return result;
}
}
public partial class MainWindow : Window
{
private ObservableCollection<SomeData> _items = new ObservableCollection<SomeData>();
public MainWindow()
{
InitializeComponent();
dataList.ItemsSource = _items;
}
private void add_Click(object sender, RoutedEventArgs e)
{
editControls.DataContext = (new SomeData() { FirstProperty = "This property has an initial value." });
editControls.BindingGroup.BeginEdit();
}
private void commit_Click(object sender, RoutedEventArgs e)
{
SomeData current = editControls.DataContext as SomeData;
if (current != null)
{
if (editControls.BindingGroup.CommitEdit())
{
_items.Add(current);
editControls.DataContext = null;
}
}
}
}
}
我正在寻找的效果是:
不幸的是,使用上面的示例代码,如果我单击“添加”然后立即单击“提交”而不填写“第二个属性”字段或更改任何内容,绑定组根本不会调用我的验证规则; CommitEdit返回“true”,对象将传递给基础集合。调用ValidateWithoutUpdate也只返回“true”。我对应用程序的测试似乎表明CommitEdit和ValidateWithoutUpdate实际上只调用验证规则:
这些方法似乎没有重新评估值未发生变化的有效规则。我认为这种行为是有道理的(也许这只是一种通用的绑定行为?),但它似乎与提交的文档相矛盾,对于CommitEdit:
如果所有验证规则都成功,则运行所有ValidationRule对象并更新绑定源。
我认为该语句中提到的验证规则只能引用BindingGroup本身的顶级规则,而不能引用单个绑定中的验证规则。无论如何,我的实际问题是:是否有可能让BindingGroup重新检查此示例中的所有验证规则;如果没有,我可以直接使用BindingExpressions集合吗?或者,我应该放弃并依赖ValidatesOnTargetUpdated(可能与不那么明显的adorner模板配对)在建立数据上下文时正确设置初始规则状态?