属性更改时未更新ListBox项

时间:2013-03-13 21:26:32

标签: c# wpf data-binding observablecollection

当集合的属性发生更改(添加/删除列表中的项目工作正常)时,我在更新包含ObservableCollection的Listbox时遇到问题:

列表框已设置ItemsSource="{Binding Path=AllPerson}",后面的代码中的数据上下文设置为此this.DataContext = allPersonClass;

allPersonClass包含ObservableCollection<Person> allPerson

Person包含名称等属性

我覆盖了人的ToString方法以返回Name属性,因此listBox显示有效数据

我尝试Person实施INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(object sender, string propertyName) {
    if (this.PropertyChanged != null) {
        PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
    }
}

public string Name {
     get { return name; }
     set {
        name = value;
        onPropertyChanged(this, "allPersonClass");
     }
}

并且在每个属性setter中都有onPropertyChanged(this, "propertyName");执行但listBox永远不会更新已创建的项

知道可能出现什么问题吗?

这是带有listBox xaml的窗口

     <Button x:Name="btnDetail" Content="Detail" HorizontalAlignment="Left" Margin="361,249,0,0" VerticalAlignment="Top" Width="75" Click="ButtonDetailClick"/>
     <ListBox x:Name="listPerson" ItemsSource="{Binding Path=AllPerson}" HorizontalAlignment="Left" Height="170" Margin="33,29,0,0" VerticalAlignment="Top" Width="155" IsSynchronizedWithCurrentItem="True"/>
     <Button x:Name="btnLoad" Content="Load" HorizontalAlignment="Left" Margin="58,249,0,0" VerticalAlignment="Top" Width="75" Click="btnLoad_Click"/>
     <Button x:Name="btnSave" Content="Save" HorizontalAlignment="Left" Margin="138,249,0,0" VerticalAlignment="Top" Width="75" Click="ButtonSaveClick"/>

这是DetailView窗口的一部分,其中进行了修改(绑定到Person)

<TextBox Text="{Binding Path=Name}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />

这里是部分AllPersonClass:

public class AllPersonClass {
  private ObservableCollection<Person> allPerson;

public AllPersonClass() {
     allPerson = new ObservableCollection<Person>();
  }

public ObservableCollection<Person> AllPerson {
     get { return allPerson; }
     set { allPerson = value; }
  }

 public void addPerson(Person newPerson) {
     allPerson.Add(newPerson);
  }


public Person getPerson(int personIndex) {
     return allPerson[personIndex];
  }
}

修改

这是在详细视图中保存更改的方法的相关部分

private void OnBtnSaveClick(object sender, RoutedEventArgs e) {
     person.Name = txtName.Text;
     person.SurName = txtSurName.Text;
}

请注意,更改是在'ObservableCollection allPerson'中进行的,只有listBox保持显示旧数据

4 个答案:

答案 0 :(得分:10)

如果您希望在更改Person属性时更新UI,则必须通知该属性已更改,而不是类

public string Name 
{
     get { return name; }
     set 
     {
        name = value;
        onPropertyChanged(this, "allPersonClass");
     }
}

<TextBox Text="{Binding Path=Name}" .....

应该是

public string Name 
{
     get { return name; }
     set 
     {
        name = value;
        onPropertyChanged(this, "Name");
     }
}

<TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" .....

您无需覆盖ToString()模型上的Person以便在ListBox中正确显示,您可以设置ListBox DisplayMemberPath来显示您想要的属性ListBox

  <ListBox ItemsSource="{Binding Path=AllPerson}" DisplayMemberPath="Name" />

编辑:回答您的评论问题:

public string Name 
{
     get { return name; }
     set 
     {
        name = value;
        onPropertyChanged(this, "Name");
        onPropertyChanged(this, "Display");
     }
}

public string Surname
{
     get { return surname; }
     set 
     {
        surname= value;
        onPropertyChanged(this, "Surname");
        onPropertyChanged(this, "Display");
     }
}

public string Display
{
     get { return Name + " " + Surname; }
}

答案 1 :(得分:5)

在DetailView中,您需要定义一个TwoWay-Binding来更新person类的属性名称。

<TextBox Text="{Binding Path=Name, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />

此外,如果您想在每次写入文本时更新属性,还需要使用UpdateSourceTrigger定义PropertyChanged。否则,属性仅在TextBox失去焦点时才更新。

<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />

答案 2 :(得分:4)

您的问题是您的收藏品从未通知您的PropertyChanged

这应该可以帮到你

ObservableCollection<INotifyPropertyChanged> items = new ObservableCollection<INotifyPropertyChanged>();
    items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(items_CollectionChanged);


    static void items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        foreach (INotifyPropertyChanged item in e.OldItems)
            item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);

        foreach (INotifyPropertyChanged item in e.NewItems)
            item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
    }

    static void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

另请参阅此Link

答案 3 :(得分:3)

我想您可能想要查看您在项目级别进行绑定的方式。看看这个链接,它会让你入门:

How to determine if a row in ObservableCollection<T> actually changed