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
值。您只需要在此更新之前执行所需的操作。