wpf 从 ObservableCollection 添加或删除项目时,列表框不更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18231678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Listbox not updating when items added or removed from ObservableCollection
提问by Ray Brennan
I have a "Hello World" type application.
A listbox.ItemsSource = Players. Players is an ObservableCollection of Player that implements INotifyPropertyChanged.
我有一个“Hello World”类型的应用程序。
一个 listbox.ItemsSource = Players。Players 是实现 INotifyPropertyChanged 的 Player 的 ObservableCollection。
When I add items in the Players constructor the items are displayed fine. When I update an existing item the changes are reflected. But when I add or remove items for the ObserveableCollection the listbox does not reflect the Items added / removed.
当我在 Players 构造函数中添加项目时,项目显示正常。当我更新现有项目时,会反映更改。但是当我为 ObserveableCollection 添加或删除项目时,列表框不反映添加/删除的项目。
xaml in MainPage:
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>
The listbox is bound in the code behind:
列表框绑定在后面的代码中:
lstPlayers.ItemsSource = plys;
Player Class:
球员等级:
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 class:
球员等级:
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" });
}
}
}
I can UPDATE an existing item in the list by using the code behind in the MainPage with
我可以通过使用 MainPage 中的代码来更新列表中的现有项目
var itm = lstPlayers.SelectedItem as TcrPlayer;
itm.Name = "Fred";
but I can't reflect any changes made to the number of items in the Players collection.
但我无法反映对 Players 集合中的项目数量所做的任何更改。
回答by Matthew Walton
TcrPlayersderives from List<TcrPlayer>and adds items to itself. However, the ObservableCollection<TcrPlayer>property isn't connected to that list in any way whatsoever. Assuming that plysis a TcrPlayersyou're not binding to an ObservableCollectionat all - you're binding to a non-observable List.
TcrPlayers从List<TcrPlayer>自身派生和添加项目。但是,该ObservableCollection<TcrPlayer>属性不以任何方式连接到该列表。假设这plys是一个TcrPlayers你根本没有绑定到一个ObservableCollection- 你绑定到一个不可观察的List。
Inheriting from ObservableCollection<TcrPlayer>instead of List<TcrPlayer>and removing the unused property might get you closer to where you want to be.
继承ObservableCollection<TcrPlayer>而不是List<TcrPlayer>删除未使用的属性可能会让您更接近您想要的位置。
As an aside, you don't see this pattern used very often because inheriting from a collection class isn't generally considered very useful unless you're adding new functionality. Usually you'd just have an ObservableCollection<TcrPlayer>property of the parent viewmodel and bind the listbox's ItemsSourceto that.
顺便说一句,您不会经常看到这种模式的使用,因为从集合类继承通常不被认为非常有用,除非您要添加新功能。通常你只拥有ObservableCollection<TcrPlayer>父视图模型的一个属性并将列表框绑定ItemsSource到它。
Speaking of which, you're also setting ItemsSourcetwice - in your XAML to {Binding}i.e. the current DataContext, and in the codebehind.
说到这一点,您还设置了ItemsSource两次 - 在 XAML 中设置为{Binding}ie current DataContext,并在代码隐藏中设置。
回答by SvenG
You don't use your ObservableCollection. Instead your TcrPlayersclass is a list itself (derives from List<T>).
你不使用你的ObservableCollection. 相反,您的TcrPlayers课程本身就是一个列表(源自List<T>)。
Either derive from ObservableCollectionand remove your ItemsProperty or use Items.Add(..)instead of Add().
无论是从派生ObservableCollection并删除您的Items属性或使用Items.Add(..)替代Add()。
E.g.
例如
public class TcrPlayers : ObservableCollection<TcrPlayer>
{
..
or
或者
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"});
}

