嵌套对象更改时更新绑定

时间:2011-09-11 21:40:58

标签: wpf object binding nested

我有一些XAML如下(一个简单的标签和按钮):

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Test="clr-namespace:WpfApplication2">
<StackPanel DataContext="{Binding Path=TestPerson}">
    <Label Content="{Binding Path=Name}"></Label>
    <Button Content="Button" Click="button1_Click" />
</StackPanel>
</Window>

在我背后的代码中:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private Person _person = new Person();
    public Person TestPerson { get { return _person; } }

    public MainWindow()
    {           
        DataContext = this;
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        _person.Name = "Bill";
        //_person = new Person() { Name = "Bill" };
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("TestPerson"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

和类Person是:

public class Person
{
    string _name = "Bob";

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

实际上,触发Propertychanged事件不会导致Label的内容更改为Bill。

我发现我能够通过以下方式克服这个问题:

  • 将新对象分配给_person(如注释掉的行中所示)
  • 从StackPanel中删除DataContext并将Label绑定到Path = TestPerson.Name

我不明白为什么我必须为_person分配一个新对象以便更新Label,或者在绑定中使用FULL路径。

有没有办法更新Label 而不用提供完整路径(依赖于DataContext),而没有为_person分配新对象?

2 个答案:

答案 0 :(得分:4)

您为PropertyChanged实例Person举起TestPerson。但是,TestPerson没有更改,Name的{​​{1}}属性已更改,这是TestPerson绑定的属性。

修改:回答前两个版本的工作原理

  

将新对象分配给_person(如注释掉的行中所示)

在这里,您实际上正在更改Label的值,并且因为TestPerson由子项继承,DataContext也会获得新的Label,这就是为什么{ {1}}已更新。

  

从StackPanel中删除DataContext并将Label绑定到   路径= TestPerson.Name

这是我从未见过的。同一个绑定为DataContext中的BindingPropertyChanged订阅了TestPerson,因此对任何这些属性提升Name都会有效。

如果您想在不Person实施PropertyChanged的情况下解决此问题,可以将INotifyPropertyChanged设置更改为Person

UpdateSourceTrigger

每当Explicit更改

时手动更新<Label Name="label" Content="{Binding Path=Name, UpdateSourceTrigger=Explicit}"/>
Binding

否则,只需为Name实施private void button1_Click(object sender, RoutedEventArgs e) { _person.Name = "Bill"; BindingExpression be = label.GetBindingExpression(Label.ContentProperty); be.UpdateTarget(); if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("TestPerson")); } } 即可,

INotifyPropertyChanged

答案 1 :(得分:0)

您需要对XAML进行一些改动......

在您的代码中,不是将DataContext设置为this,而是通过绑定在XAML中设置...

     <StackPanel DataContext="{Binding RelativeSource={RelativeSource
                                            AncestorType= {x:Type Window},
                                                Mode=FindAncestor}, 
                                       Path=TestPerson}">
          <Label Content="{Binding Path=Name}"></Label>
          <Button Content="Button" Click="button1_Click" />
     </StackPanel>

删除

     DataContext = this;

来自您的代码。

如果有帮助,请告诉我。