在DataContextChanged事件期间获取UWP FrameworkElement中的旧DataContext值

时间:2018-02-12 23:17:00

标签: uwp uwp-xaml datacontext

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

1 个答案:

答案 0 :(得分:0)

你是对的! EventArgs事件的DataContextChanged并未提供我们可以从中获取旧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。 1}},通过OldDataContextProperty属性。

用户控件的布局非常简单,由单个OldDataContext(可能是其他任何东西)组成,它公开了ComboBox事件,其事件处理程序已在上面定义:

DataContextChanged

在MainPage的布局中,我实例化了这个自定义用户控件:

<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>

在代码隐藏中,我初始化了两种类型的Lists变量,一种是类型<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

结果是假装:

  

旧数据背景:

     

新数据上下文: System.Collections.Generic.List`1 [System.String]

     

旧数据上下文: System.Collections.Generic.List`1 [System.String]

     

新数据上下文: System.Collections.Generic.List`1 [System.Int32]

当我们第一次激发DataContextChanged事件时,OldDataContextProperty保存默认值,该值为null(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; } } 构造函数中指定的值),而当前PropertyMetaData属性设置为第一个List集合。

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