当ObservableCollection中添加或删除项时,Listbox未更新

3

我有一个类似于“Hello World”的应用程序。

一个列表框的 ItemsSource 是 Players。Players 是一个实现了 INotifyPropertyChanged 接口的 Player 的 ObservableCollection。

当我在 Players 构造函数中添加项时,这些项可以被正确显示。

当我更新已存在的项时,更改会被反映出来。

但是,当我向 ObserveableCollection 中添加或删除项时,列表框没有反映出添加/删除的项。

MainPage 中的 XAML 代码:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <ListBox Name="lstPlayers" ItemsSource="{Binding}" Margin="12,66,13,24" Grid.Row="1">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <!--<StackPanel Background="#FFD1D1D1">-->
                    <Grid Margin="0,0,0,0" Grid.RowSpan="2">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="60"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" Text="{Binding Number}" FontSize="48"  />
                        <TextBlock Grid.Column="1" Text="{Binding Name}" FontSize="48" />
                    </Grid>
                    <!--</StackPanel>-->
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Content="Button" Height="95" HorizontalAlignment="Left" Margin="183,350,0,0" Name="button1" VerticalAlignment="Top" Width="260" Click="button1_Click" />
        <Button Content="Button" Height="72" HorizontalAlignment="Left" Margin="198,472,0,0" Name="button3" VerticalAlignment="Top" Width="232" Click="button3_Click" />
    </Grid>

列表框在代码后台被绑定:
  lstPlayers.ItemsSource = plys;

玩家类:

using System.ComponentModel;
namespace DatabindList
{
public class TcrPlayer : INotifyPropertyChanged
{


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

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {

            if (_name != value)
                _name = value;

            NotifyPropertyChanged("Name");

        }
    }
   }
}

Players类:

using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace DatabindList
{

public class TcrPlayers : List<TcrPlayer> 
{
    public ObservableCollection<TcrPlayers> Items { get; private set; }



    public TcrPlayers()
    {
        //these are displayed
        Add(new TcrPlayer { Name = "Christine"});
        Add(new TcrPlayer { Name = "Janet"});
        Add(new TcrPlayer { Name = "Ian"});
    }


    public void AddPlayer()
    {
        //THIS HAS NO EFFECT ON THE LISTBOX
        Add(new TcrPlayer { Name = "Newbie", Number = "99" });

    }


   }
}

我可以使用MainPage中的后台代码更新列表中的现有项目:

我可以使用MainPage中的后台代码更新列表中的现有项目:

            var itm = lstPlayers.SelectedItem as TcrPlayer;
            itm.Name = "Fred";

但是我无法反映出对Players集合中项目数量所做的任何更改。


你尝试过使用 public class TcrPlayers : ObservableCollection<TcrPlayer> 吗?据我所见,你甚至没有使用 Items 属性并添加到 List<TcrPlayer> 中。 - dkozl
2个回答

5

TcrPlayers 继承自 List<TcrPlayer> 并向其添加项目。然而,ObservableCollection<TcrPlayer> 属性与该列表没有任何连接。假设 plys 是一个 TcrPlayers,您并未绑定到可观察的 ObservableCollection - 您正在绑定到非可观察的 List

如果从 List<TcrPlayer> 改为继承自 ObservableCollection<TcrPlayer> 并删除未使用的属性,这可能会更接近您想要的结果。

顺便说一句,您不经常看到这种模式的使用,因为继承自集合类通常被认为没有多大用处,除非您添加了新功能。通常,您只需要在父视图模型中拥有一个 ObservableCollection<TcrPlayer> 属性,并将 listbox 的 ItemsSource 绑定到该属性。

说到这里,您还将 ItemsSource 设置两次 - 在 XAML 中设置为 {Binding},即当前的 DataContext,以及在代码后台中设置。


天啊!现在看起来好简单,但我花了4个多小时才搞明白。非常感谢 :) - Ray Brennan
没问题。我恰好做了很多这样的事情,所以一旦你做了六十次,它就非常明显了! - Matthew Walton

2

您没有使用您的ObservableCollection。相反,您的TcrPlayers类本身就是一个列表(派生自List<T>)。

要么从ObservableCollection派生并删除您的Items属性,要么使用Items.Add(..)而不是Add()

例如:

public class TcrPlayers : ObservableCollection<TcrPlayer> 
{
..

或者

public class TcrPlayers
{
    public ObservableCollection<TcrPlayers> Items { get; private set; }

    public TcrPlayers()
    {
        //these are displayed
        Items.Add(new TcrPlayer { Name = "Christine"});
        Items.Add(new TcrPlayer { Name = "Janet"});
        Items.Add(new TcrPlayer { Name = "Ian"});
    }

我只能标记一个答案为正确,而Matthew先到了那里:/ 谢谢Sven。 - Ray Brennan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接