Привязка данных + DataGrid - как подключиться? - PullRequest
0 голосов
/ 23 ноября 2011

Этот вопрос является результатом моего предыдущего вопроса DataGrid - выбор сетки сбрасывается при поступлении новых данных

====================================================================

У меня есть такая DataGrid

<DataGrid AutoGenerateColumns="True" HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" ItemsSource="{Binding DataList}" IsReadOnly="True"/>

В моем ViewModel у меня есть такое поле:

public ObservableCollection<ConsoleData> DataList { get; set; }

И такой метод, который вызывается каждую секунду:

private void model_DataArrived(List<ConsoleData> dataList)
{
    DataList.Clear();
    dataList.ForEach(x => DataList.Add(x));
}

=====================================================================

Мы выяснили, что, поскольку я вызываю DataList.Clear выбор в элементе управления пользовательского интерфейсаочищен, и я не хочу, чтобы это произошло.Поэтому, скорее всего, я не должен заменять экземпляры ConsoleData на ViewModel, вместо этого я должен update эти экземпляры.

Но ObservableCollection наблюдает за добавлением / удалением, я думаю, и не наблюдает за update, не так ли?Так что, если я буду update, экземпляры DataBinding не будут работать?

Другая проблема с текущим приложением состоит в том, что dataList.ForEach(x => DataList.Add(x)); заставляет привязку данных выполнять на каждой итерации, а не только в конце?

В целом, как правильно делать то, что я хочу делать, потому что текущее приложение не работает и имеет слишком много проблем ...

Ответы [ 5 ]

1 голос
/ 23 ноября 2011

Непонятно, как вы планируете обновить элемент в вашем ObservableCollection.Есть как минимум два способа сделать это.Один из способов - обновить все свойства, которые изменены в объекте ConsoleData.В этом случае вы должны использовать ConsoleData INotifyPropertyChanged.Другим способом является прямое обновление элемента в ObservableCollection.Для этого вы можете использовать SetItem метод ObservableCollection.Это вызовет событие CollectionChanged, как указывает документация MSDN для SetItem.

Поскольку вы указали, что используете MVVM, общепринятым будет сделатьВаш ObservableCollection будет коллекцией ConsoleDataViewModel вместо ConsoleData.

Другая проблема с текущим приложением состоит в том, что dataList.ForEach(x => DataList.Add(x)); заставляет привязку данных выполнять на каждой итерации вместо выполнения только в конце?

Не думаю, что у вас возникнет проблема с обновлением, если вы измените свой метод model_DataArrived для обновления вместо очистки / добавления, как указано выше.

1 голос
/ 23 ноября 2011

Проблема в том, что ObservableCollection не уведомляет об изменении элемента; он уведомляет только, когда элементы добавляются и удаляются, как вы говорите. Чтобы решить эту проблему, я создал класс, который я называю VeryObservableCollection. Для каждого добавленного объекта он подключает событие NotifyPropertyChanged объекта к обработчику, который вызывает событие CollectionChanged. Для каждого удаленного объекта он удаляет обработчик. Очень просто и должно решить вашу проблему. Вам просто нужно убедиться, что вы реализовали NotifyPropertyChanged для объектов, хранящихся в коллекции. Например:

public class VeryObservableCollection<T> : ObservableCollection<T>

/// <summary>
/// Override for setting item
/// </summary>
/// <param name="index">Index</param>
/// <param name="item">Item</param>
protected override void SetItem(int index, T item)
{
    try
    {
        INotifyPropertyChanged propOld = Items[index] as INotifyPropertyChanged;
        if (propOld != null)
            propOld.PropertyChanged -= new PropertyChangedEventHandler(Affecting_PropertyChanged);
    }
    catch (Exception ex)
    {
        Exception ex2 = ex.InnerException;
    }
    INotifyPropertyChanged propNew = item as INotifyPropertyChanged;
    if (propNew != null)
        propNew.PropertyChanged += new PropertyChangedEventHandler(Affecting_PropertyChanged);

    base.SetItem(index, item);
}
0 голосов
/ 23 ноября 2011

ОК, во-первых, нам нужно понять, что элемент, который был источником выделения на любых элементах управления Selector, таких как ListBox, DataGrid и т. Д., Если он будет удален, потеряет выделение.

Для этого, пожалуйста, используйте массовое добавление и однократное уведомление FastObservableCollection .

Но чтобы сохранить такой выбор, вам нужно будет установить для выбранного элемента / значения значение DataGrid после того, как Clear и AddRange произойдет.

0 голосов
/ 23 ноября 2011

, если ваши ConsoleData реализуют INotifyPropertyChanged, вы можете просто обновить их, и вы увидите изменения в вашем интерфейсе - без потери выбора.

0 голосов
/ 23 ноября 2011

Я думаю, вы можете сделать что-то вроде этого

private ObservableCollection<ConsoleData> dataList;
public ObservableCollection<ConsoleData> DataList 
{ 
   get {return dataList; } 
   set {dataList = value;} 
}

А ваши манипуляции с данными имеют доступ только к полю dataList. Однажды законченная манипуляция вынуждает DataBinding обновить или переназначить ее, заставив Biding подать уведомление в WPF.

Должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...