我有个坏消息要告诉你。
检查位于DependencyObject.SetValue 内部,用于验证新值是否等于旧值。因此,如果您绑定到A.B,并且更改A.B.C 会为A.B 产生PropertyChanged 事件,Binding mechanizm 将处理此事件,甚至调用DependencyObject.SetValue。但是随后(由于新旧A.B 值相等)将不会对DP 应用任何更改。
为了实现正确的 DP 触发,您应该创建 A.B 的新实例,结果令人头疼。
更新
您可以使用 Freezable 对象,该对象支持在其属性更改时通知它已更改。 DependencyObject 可以正确地与 Freezables 一起使用,因此下一个示例可以满足您的需要。
模型类:
public class A
{
public A()
{
this.B = new B();
}
public B B
{
get; private set;
}
}
public class B : Freezable, INotifyPropertyChanged
{
protected override Freezable CreateInstanceCore()
{
return new B();
}
private string _c = "initial string";
public string C
{
get
{
return _c;
}
set
{
this._c = value;
this.OnPropertyChanged("C");
this.OnChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
var safe = this.PropertyChanged;
if (safe != null)
{
safe(this, new PropertyChangedEventArgs(name));
}
}
}
Xaml:
<StackPanel>
<TextBox Text="{Binding A.B.C}" />
<TextBox Text="{Binding MyProperty.C}" />
<Button Click="Button_Click"/>
</StackPanel>
后面的代码:
public partial class TextBoxesView : UserControl
{
public TextBoxesView()
{
InitializeComponent();
this.A = new A();
this.DataContext = this;
BindingOperations.SetBinding(this, TextBoxesView.MyPropertyProperty, new Binding("A.B"));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.A.B.C = DateTime.Now.ToString();
}
public A A
{
get;
private set;
}
public B MyProperty
{
get
{
return (B)this.GetValue(TextBoxesView.MyPropertyProperty);
}
set
{
this.SetValue(TextBoxesView.MyPropertyProperty, value);
}
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty",
typeof(B),
typeof(TextBoxesView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, (d, e) => { }));
}