【问题标题】:Get the old DataContext value in UWP FrameworkElement during a DataContextChanged event在 DataContextChanged 事件期间获取 UWP FrameworkElement 中的旧 DataContext 值
【发布时间】:2018-07-23 06:03:27
【问题描述】:

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

【问题讨论】:

    标签: uwp uwp-xaml datacontext


    【解决方案1】:

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

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

    所以我首先定义了一个名为 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>
    

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

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

    在代码隐藏中,我初始化了两种类型的 Lists 变量,一种类型为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 属性设置为第一个 List 集合。

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

    【讨论】:

    • 我尝试了这个建议,奇怪的是,当我将 OldDataContext 绑定到 DataContext 以便我可以拦截两者的更改时,OldDataContext 更改发生** BEFORE ** DataContext
    • 您不应该为这个新的依赖属性要求任何绑定 imo。 Simpy 跟踪您的 DataContextChanged 事件,并且仅在您执行所需操作后将您的 OldDataContext 依赖属性更改为新值。它相当简单,但很有效。
    • 更新答案。
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 2015-03-21
    • 1970-01-01
    • 2021-10-23
    • 2014-06-29
    相关资源
    最近更新 更多