绑定到ObservableCollection的ListBox不会更新

时间:2012-02-08 04:46:02

标签: c# wpf binding listbox observablecollection

我无法使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"); }
    }
}

目前,绑定在启动时有效。应用程序将绑定并正确显示每个对象的名称。例如,这是一个执行相同实现的测试应用程序: enter image description here

在我的主要实际应用程序中,我调用了异步方法(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更新?

2 个答案:

答案 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" />