在DataContextChanged事件中,在UWP Frameworkelement中获取旧的DataContext



Windows Universal Platform在很多方面与WPF非常相似,但也非常不同。在WPF中,在DataContextChanged事件中,我可以从DataContextChangedEventArgs.OldValue获得数据上下文的旧值,而DataContextChangedEventArgs.NewValue的新值。在UWP中,只有NewValue。在DataContextChanged事件中,如何获得旧值,例如在 INotifyPropertyChanged的实施者的情况下,从旧的DataContext值中删除事件处理程序注册?我正在编写自定义控件(是的,绝对需要进行自定义(,我需要确保对此控件的内部事件处理程序的添加和删除是对称的。

你是对的!DataContextChanged事件的EventArgs不提供我们可以从中获得旧DataContext值的属性。

但是,由于您正在创建自定义控件,因此我认为一个干净的选项可能是在您的自定义控件上注册自定义依赖项属性,其唯一目的是存储旧的DataContext值,每当发生DataContextChanged事件时进行更新。

所以我首先定义一个名为 CustomUserControl的usercontrol:

    public sealed partial class CustomUserControl : UserControl
    {
        public CustomUserControl()
        {
            this.InitializeComponent();
        }
        public static readonly DependencyProperty OldDataContextProperty =
            DependencyProperty.Register(
                "OldDataContext",
                typeof(object),
                typeof(CustomUserControl),
                new PropertyMetadata(null)
            );
        public object OldDataContext
        {
            get
            {
                return GetValue(OldDataContextProperty);
            }
            set
            {
                SetValue(OldDataContextProperty, value);
            }
        }
        private void RootObject_DataContextChanged(FrameworkElement sender, 
     DataContextChangedEventArgs args)
        {
            System.Diagnostics.Debug.WriteLine("Old Data Context: " + OldDataContext);
            System.Diagnostics.Debug.WriteLine("New Data Context: " + DataContext);

            OldDataContext = args.NewValue;
        }
    }

每当发生DataContextChanged事件时,我们首先将对象集的类型分析为自定义控件的旧/新DataContext,只需通过OldDataContext属性访问自定义依赖项 OldDataContextProperty

用户控件的布局相当简单,由单个ComboBox组成(可能是其他任何东西(,它揭示了DataContextChanged事件,该事件的事件处理程序已在上面定义:

<UserControl
    x:Class="UserControlForStackOverflow.CustomUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UserControlForStackOverflow"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
    <ComboBox x:Name="RootObject" DataContextChanged="RootObject_DataContextChanged" />
</UserControl>

在主页的布局中,我实例化了此自定义用户控件:

<Page
    x:Class="UserControlForStackOverflow.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UserControlForStackOverflow"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <local:CustomUserControl x:Name="CustomControl" />
</Page>

在代码范围内,我已经初始化了两种类型的列表变量,一个类型string和另一种int类型,以了解OldDataContextProperty依赖关系属性是否按预期工作。

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        List<string> list1 = new List<string> { "aaa", "bbb", "ccc" };
        List<int> list2 = new List<int> { 1, 2, 3 };
        CustomControl.DataContext = list1;
        CustomControl.DataContext = list2;
    }
}

结果是假装:

旧数据上下文:

新数据上下文: system.collections.generic.list'1 [system.string]

旧数据上下文: system.collections.generic.list'1 [system.string]

新数据上下文: system.collections.generic.list`1 [system.int32]

当我们首次启动DataContextChanged事件时,OldDataContextProperty保留默认值,该值为null( PropertyMetaData构造函数中指定的值(,而当前DataContext属性则将当前属性设置为第一个列表集合。

当我们将自定义控件的DataContext更改为保存第二个列表时,我们可以看到OldDataContextProperty仍然对第一个对象集作为控件的DataContext,并将对其进行引用,直到执行到达末端RootObject_DataContextChanged EventHandler将将OldDataContextProperty设置为当前DataContext值。您只需要在此更新之前执行所需的操作。

最新更新