ListBox, связанный с ObservableCollection, не обновляется - PullRequest
0 голосов
/ 08 февраля 2012

У меня проблемы с получением привязки 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 вещи BeginConnect, BeginSend и т. Д.), Которые используют обратные вызовы, которые могут обновить коллекцию. (Это список игроков, поэтому при получении определенных пакетов список обновляется с их данными.)

Моя проблема в том, что коллекция обновляется внутри одного из асинхронных обратных вызовов, которые не обновляются в списке. Данные коллекции обновляются должным образом, установка разрыва в основном коде в любом месте показывает, что коллекция обновляется, но список никогда не обновляется, чтобы отразить изменения. Так что он просто говорит одно и то же, несмотря ни на что.

Я что-то упустил?

Я также пытался использовать CollectionViewSource, чтобы разрешить фильтрацию, и у него та же проблема.

== РЕДАКТИРОВАТЬ ==

Я обнаружил, что проблема заключается в том, как инициализируется коллекция. Вместо использования внутреннего элемента копирования при инициализации коллекции мне нужно было использовать открытое свойство, чтобы оно могло обновлять пользовательский интерфейс.

Так что с помощью следующего исправили это:

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 возвращает меня к проблемам с обновлением. Так есть ли способ отфильтровать это вручную и обновлять пользовательский интерфейс?

Ответы [ 2 ]

2 голосов
/ 08 февраля 2012

Моя проблема, когда коллекция обновляется внутри одного из асинхронных обратные вызовы не обновляются в списке.

Ну, вот в чем проблема! Наблюдаемые коллекции не являются потокобезопасными. Вы должны сделать их такими.

Нет TwoWay режима связывания или UpdateSourceTrigger=PropertyChanged поможет в этом случае, так как проблема заключается в многопоточности в вашем коде ...

Используйте эту пользовательскую реализацию поточно-ориентированной и быстрой наблюдаемой коллекции для вашего удобства ...

Быстродействующий и потокобезопасный наблюдаемый набор

Что касается интерфейса INotifyPropertyChanged, его 'PropertyChanged event is automatically dispatched to the UI thread. So any multithreaded context updating the properties of a class that implements INotifyPropertyChanged` обновит графический интерфейс.

Дайте мне знать, если это поможет,

0 голосов
/ 08 февраля 2012

UpdateSourceTrigger = PropertyChanged отсутствует

<ListBox x:Name="lstMyList" ItemsSource="{Binding Path=Objects,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="Name" />
...