我无法使ListBox绑定按预期工作。我目前正在尝试将ListBox绑定到单个公开的ObservableCollection项。这些项目本身就是一个单独的类。目前,我这样绑定:
<Window x:Class="toxySharp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:classes="clr-namespace:MyApplication.Classes"
Title="MainWindow" Height="325" Width="400"
DataContext="{Binding Source={x:Static local:SingletonClass.Instance}}">
<Grid x:Name="LayoutRoot">
<ListBox x:Name="lstMyList" ItemsSource="{Binding Path=Objects, Mode=TwoWay}" DisplayMemberPath="Name" />
</Grid>
</Window>
我的单身人士是这样的基本实现:
public class SomeObject : INotifyPropertyChanged
{
private Int32 m_vId;
private String m_vName;
public SomeObject() { }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public Int32 Id
{
get { return this.m_vId; }
set { this.m_vId = value; NotifyPropertyChanged("Id"); }
}
public String Name
{
get { return this.m_vName; }
set { this.m_vName = value; NotifyPropertyChanged("Name"); }
}
}
public class SingletonClass : INotifyPropertyChanged
{
private static SingletonClass m_vInstance;
private ObservableCollection<SomeObject> m_vObjects;
private SingletonClass()
{
this.m_vObjects = new ObservableCollection<SomeObject>();
for (int x = 0; x < 255; x++)
this.m_vObjects.Add(new SomeObject() { Id = x, Name = String.Format("{0} - new object", x) });
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public static SingletonClass Instance
{
get
{
if (m_vInstance == null)
m_vInstance = new SingletonClass();
return m_vInstance;
}
}
public ObservableCollection<SomeObject> Objects
{
get { return this.m_vObjects; }
set { this.m_vObjects = value; NotifyPropertyChanged("Objects"); }
}
}
目前,绑定在启动时有效。应用程序将绑定并正确显示每个对象的名称。例如,这是一个执行相同实现的测试应用程序:
在我的主要实际应用程序中,我调用了异步方法(Socket stuff BeginConnect,BeginSend等),它们使用可以更新集合的回调。 (这是一个播放器列表,因此当收到某些数据包时,列表会随其数据一起更新。)
我的问题是当集合在其中一个异步回调中更新时,它不会在列表上更新。正确更新集合数据,在主代码中设置中断,显示集合正在更新,但列表框永远不会更新以反映更改。因此无论如何,它都会一直说同样的事情。
我忽略了什么吗?
我也尝试过使用CollectionViewSource来允许过滤,这也有同样的问题。
==编辑==
我发现问题出在单例中,如何初始化集合。在初始化集合时,我不需要使用内部复制成员,而是需要使用公开的属性来允许它更新UI。
所以使用以下修复它:
private SingletonClass()
{
this.Objects = new ObservableCollection<SomeObject>();
for (int x = 0; x < 255; x++)
this.Objects.Add(new SomeObject() { Id = x, Name = String.Format("{0} - new object", x) });
}
但是现在列表绑定工作了,我希望能够根据对象类中的另一个属性来过滤它。 (在示例SomeObject中)。我有一个布尔表明对象是否处于活动状态。试图绑定到CollectionViewSource会让我回到不更新的问题。那么有没有办法手动过滤这个并保持ui更新?
答案 0 :(得分:2)
我的问题是在其中一个异步内更新集合 它没有在列表上更新回调。
那就是问题不是它!可观察集合不是线程安全的。你需要这样做。
在这种情况下,没有TwoWay
绑定模式或UpdateSourceTrigger=PropertyChanged
会有所帮助,因为问题在于代码中的多线程......
使用此自定义实现的线程安全和更快的可观察集合,以方便您...
Fast performing and thread safe observable collection
就INotifyPropertyChanged
接口而言,其'PropertyChanged event is automatically dispatched to the UI thread. So any multithreaded context updating the properties of a class that implements
INotifyPropertyChanged`将更新GUI。
如果有帮助,请告诉我,
答案 1 :(得分:0)
UpdateSourceTrigger =缺少PropertyChanged
<ListBox x:Name="lstMyList" ItemsSource="{Binding Path=Objects,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="Name" />