我有一个INotifyPropertyChanged
数据结构,它是用户控件的依赖属性。数据结构的属性之一绑定到控件的元素之一。
MyData.cs(使用 MVVM Light 实现INotifyPropertyChanged
):
public class MyData : ObservableObject
{
private string _text;
public string Text
{
get { return _text; }
set { Set(() => Text, ref _text, value); }
}
public override string ToString()
{
return Text;
}
}
文本控件.xaml:
<UserControl x:Class="UITester.TextControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Name="This"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox Text="{Binding ElementName=This, Path=Data.Text, Mode=TwoWay}"></TextBox>
</Grid>
</UserControl>
文本控制.xaml.cs:
public partial class TextControl : UserControl
{
public static MyData DefaultData = new MyData {Text = "Default"};
public MyData Data
{
get { return (MyData)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(MyData), typeof(TextControl), new PropertyMetadata(DefaultData));
public TextControl()
{
InitializeComponent();
}
}
现在我想要的是DataProperty
每当其内部属性之一发生更改时,依赖属性得到更新(即通知任何感兴趣的人它已更改)。
我通过两种方式对此进行测试:
通过将依赖属性绑定
Data
到Label
MyControlText
并通过在其中创建依赖属性并将控件和 aMainWindow
绑定到它。Data
Label
MainWindow.xaml:
<Window x:Class="UITester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:uiTester="clr-namespace:UITester"
Title="MainWindow" Height="350" Width="525"
x:Name="me">
<StackPanel DataContext="{Binding ElementName=me}">
<uiTester:TextControl x:Name="MyControl" Data="{Binding ElementName=me, Path=MyControlText}"></uiTester:TextControl>
<Label Content="{Binding ElementName=MyControl, Path=Data}"></Label>
<Label Content="{Binding ElementName=me, Path=MyControlText}"></Label>
<Button Click="SetButtonClick">Set</Button>
<Button Click="ResetButtonClick">Reset</Button>
</StackPanel>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
private readonly Dictionary<int, int> _selected = new Dictionary<int, int>();
public MainWindow()
{
InitializeComponent();
//list.ItemsSource = _selected.Values;
}
private void SetButtonClick(object sender, RoutedEventArgs e)
{
MyControlText = new MyData{Text = "new"};
}
private void ResetButtonClick(object sender, RoutedEventArgs e)
{
MyControlText = null;
}
public MyData MyControlText
{
get { return (MyData)GetValue(MyControlTextProperty); }
set { SetValue(MyControlTextProperty, value); }
}
// Using a DependencyProperty as the backing store for MyControlText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyControlTextProperty =
DependencyProperty.Register("MyControlText", typeof(MyData), typeof(MainWindow), new PropertyMetadata(new MyData{ Text = ""}));
}
当我更改TextBox
控件内部时,我希望更新依赖属性Data
,因此我希望我的两个Label
s 都更新。
这不起作用,所以我尝试注册明确更改的属性:
public partial class TextControl : UserControl
{
public static MyData DefaultData = new MyData {Text = "Default"};
public MyData Data
{
get { return (MyData)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(MyData), typeof(TextControl), new PropertyMetadata(DefaultData) { PropertyChangedCallback = TextPropertyChanged });
private static void TextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var c = (TextControl) d;
if (e.NewValue != null)
{
((MyData) e.NewValue).PropertyChanged += (s, ea) =>
{
c.GetBindingExpression(DataProperty).UpdateSource();
};
}
}
public TextControl()
{
InitializeComponent();
}
}
我认为这样每当我设置一个新的依赖属性时,我都会注册到它的任何属性发生变化的事件。在处理程序中,我希望更新绑定到依赖项属性的所有元素。但这也没有用...
我知道控件内部的绑定是有效的,因为当我在UpdateSource
代码处设置断点时确实会中断,但我不明白如何更新整个依赖属性(以及绑定到它的标签)。
更新:我也尝试调用 'd.InvalidateProperty(DataProperty);' 而不是 'c.GetBindingExpression(DataProperty).UpdateSource();' 但它也没有工作......