构造函数注入与数据上下文的静态绑定时的Validation.ErrorEvent行为差异

时间:2017-02-20 22:49:19

标签: c# wpf validation xaml

概述

我有两个视图,一个通过ContentControl声明包含在另一个视图中。包含视图的视图模型通过其构造函数注入其视图模型,并在其中设置DataContext。较低的包含视图使用视图模型定位器类通过XAML声明获取其DataContext。我们使用挂钩到Validation.ErrorEvent处理程序的自定义ValidationHelper类,以支持包含的视图能够通知其父视图有关任何数据验证错误。

然而,我不理解的行为有所不同。当使用此方法在下层视图的XAML中静态绑定DataContext时,错误处理程序会激活较低的包含视图一次,然后加载两个控件。但是,如果我切换下部视图以对其视图模型使用构造函数注入并在构造函数中设置DataContext,则相同的Error处理程序会在父视图和子视图都加载之前调用它们。

代码

上层视图的XAML代码

<UserControl x:Class="MyUpperView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <StackPanel>
        <!-- OTHER CONTROLS ARE HERE -->
        <ContentControl Content="{Binding Path=MyLowerViewInstance, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
    </StackPanel>
</UserControl>

上层视图的XAML.cs代码

public partial class MyUpperView : UserControl
{
    public MyUpperView(MyUpperViewModel viewModel)
    {
        InitializeComponent();
        DataContext = viewModel;
    }
}

上层视图的ViewModel代码

public class MyUpperViewModel
{
    private object _sourceObjectUI;

    public object MyLowerViewInstance
    {
        get { return _sourceObjectUI; }
    }

    public MyUpperViewModel()
    {
        _sourceObjectUI = new MySourceObjectUI();
    }
}

较低视图的XAML代码

<UserControl x:Class="MyLowerView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:myns="clr-namespace:MyNamespace;assembly=MyAssembly" >

    <UserControl.Resources>
        <myns:MyViewModelLocator x:Key="MyVML" />
    </UserControl.Resources>
    <UserControl.DataContext>
        <Binding Mode="OneWay"
                 Source="{StaticResource ResourceKey=MyVML}"
                 Path="MyLowerViewModelProperty" />
    </UserControl.DataContext>

<TextBox Text="{Binding Path=MyText, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />

</UserControl>

XAML.cs低视图模型的代码(这是默认值,我只是将其包含在内以供参考)

public partial class MyLowerView : UserControl
{
    public MyLowerView()
    {
        InitializeComponent();
    }
}

低端视图的ViewModel代码

public class MyLowerViewModel : IDataErrorInfo
{
    public string MyText { get; set; }

    public string this[string columnName]
    {
        var result = string.Empty;
        switch(columnName)
        {
            case "MyText":
            {
                // Perform some validation stuff here. If the data doesn't pass validation, set the result string to something other than string.Empty
            }
        }
    }
}

此时,代码有效。创建视图时,会立即评估MyText属性是否存在任何数据错误,并在Validation上引发Error事件,就像我们已正确响应的自定义ErrorChangedHandler一样。

当我删除下部视图的UserControl.DataContext声明,而不是将MyLowerViewModel注入XAML.cs构造函数时,突然之间ErrorChangedHandler甚至被触发两次,一次用于下部视图,一次用于上部视图,即使生成事件的TextBox仅由下部视图引用。

我不明白这种行为差异。上层视图如何为一个它实际上不知道的控件引发事件,并且只有当构造函数为数据上下文注入时才较低的视图?谢谢你的帮助!

0 个答案:

没有答案