是否可以让BindingGroup.CommitEdit / ValidateWithoutUpdate始终运行所有绑定验证规则?

时间:2011-04-12 02:51:10

标签: c# wpf binding

这是我尝试使用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;
                }
            }
        }
    }
}

我正在寻找的效果是:

  • 我单击“添加项目”将对象绑定到窗口下半部分的编辑控件(在实际应用程序中提供数据上下文之前通常不可见)。
  • 我故意不在任何属性绑定上设置ValidatesOnTargetUpdated,因为我不一定要显示任何错误装饰器;字段文本已经暗示字段是必需的。
  • 当我单击Commit时,我希望BindingGroup重新检查所有验证规则,以捕获仍为空的任何字段,并在此时显示错误装饰器。

不幸的是,使用上面的示例代码,如果我单击“添加”然后立即单击“提交”而不填写“第二个属性”字段或更改任何内容,绑定组根本不会调用我的验证规则; CommitEdit返回“true”,对象将传递给基础集合。调用ValidateWithoutUpdate也只返回“true”。我对应用程序的测试似乎表明CommitEdit和ValidateWithoutUpdate实际上只调用验证规则:

  • 规则目前为假/无效。
  • 规则目前有效,但值已更改。

这些方法似乎没有重新评估值未发生变化的有效规则。我认为这种行为是有道理的(也许这只是一种通用的绑定行为?),但它似乎与提交的文档相矛盾,对于CommitEdit:

  

如果所有验证规则都成功,则运行所有ValidationRule对象并更新绑定源。

我认为该语句中提到的验证规则只能引用BindingGroup本身的顶级规则,而不能引用单个绑定中的验证规则。无论如何,我的实际问题是:是否有可能让BindingGroup重新检查此示例中的所有验证规则;如果没有,我可以直接使用BindingExpressions集合吗?或者,我应该放弃并依赖ValidatesOnTargetUpdated(可能与不那么明显的adorner模板配对)在建立数据上下文时正确设置初始规则状态?

0 个答案:

没有答案