У меня есть приложение WPF, в котором я общаюсь со вторым приложением через сокеты TCP. Каждое отправленное и полученное сообщение имеет заданную длину и информацию, которая заключена в объект.
После обработки сообщения этот объект добавляется в ObservableList, который (единожды) привязан к CollectionViewSource. Этот CollectionViewSource является Itemsource для Datagrid. Кроме того, CollectionViewSource имеет фильтр, который можно установить с помощью нескольких toggleButton. Когда соединение закрывается, список должен быть очищен для дальнейшего использования после повторного подключения.
Я протестировал эту настройку и особенно фильтрацию до нескольких тысяч записей, и, похоже, она работает нормально. За исключением того, что я очищу ObservableCollection, весь интерфейс перестанет отвечать на запросы, будет медленным, а установка фильтра приведет к увеличению используемой вычислительной мощности до 60% даже для 10 объектов в списке.
Очистка ObservableCollection, похоже, не обновляет интерфейс, а только перезаписывает коллекцию новым объектом.
Я также пытался изменить свойства в XAML, например режим привязки или режим только для чтения, но это ничего не меняет.
<CollectionViewSource x:Key = "telegramList"
Source = "{Binding Path=LogManager.TList, mode=OneWay }"
Filter = "telegramFilter">
</CollectionViewSource>
<DataGrid ItemsSource = "{Binding Source = {StaticResource telegramList}}" IsReadOnly = "True" IsSynchronizedWithCurrentItem = "False" x:Name = "
Обновлено: вот LogManager и функции, обращающиеся к списку. LogTelegram () может быть вызван либо из обратного вызова сокета, либо непосредственно из основного потока до того, как объект сообщения будет поставлен в очередь для отправки.
public class LogManager : INotifyPropertyChanged
{
private ObservableCollection<ImmutableTelegram> tList;
public ObservableCollection<ImmutableTelegram> TList { get { return tList; } set { tList = value; NotifyPropertyChanged("TList"); } }
public void logTelegram(Telegram512 telegram)
{
if (!Model.Instance.gui.Dispatcher.CheckAccess())
{
Model.Instance.gui.Dispatcher.Invoke(delegate
{
logTelegramDelegate(telegram);
});
}
else
{
logTelegramDelegate(telegram);
}
}
private void logTelegramDelegate(Telegram512 telegram)
{
if (telegram.TELETYPE == Telegram512.Types.XX)
TList.Add(new ImmutableTelegram(telegram));
if (TList != null)
TList.Add(new ImmutableTelegram(telegram));
}
public void clearTelegramLog()
{
TList = null;
}
public void createTelegramLog()
{
TList = new ObservableCollection<ImmutableTelegram>();
}
}
Здесь также есть функция фильтра и один слушатель изменения состояния для кнопки переключения.
private void dataGridFilter(object sender, FilterEventArgs e)
{
var obj = e.Item as Telegram512;
if (obj != null)
{
e.Accepted = true;
if (obj.TELETYPE == Telegram512.Types.LF && this.lfToggle.IsChecked == false)
{
e.Accepted = false;
return;
}
}
}
private void lfToggle_Click(object sender, RoutedEventArgs e)
{
if (telegramDataGrid.ItemsSource != null)
CollectionViewSource.GetDefaultView(telegramDataGrid.ItemsSource).Refresh();
}
Вероятно, это не связано с вашей проблемой, но наличие сеттера на ObservableCollection модели представления является ошибкой обычно. Обычный шаблон состоит в том, чтобы иметь только сеттер и создавать его экземпляр в конструкторе, с этого момента в коллекции выполняются только операции добавления / удаления / очистки. Поскольку сам экземпляр не изменяется, ему также не нужно поднимать PropertyChanged (коллекция внутренне вызывает события CollectionChanged по мере перемещения элементов.
@BradleyUffner Спасибо за предложение! Я уже пытался следовать этому шаблону, но я попытался увидеть, имеет ли это значение, если для списка установлено значение null, а затем создается новый экземпляр при нажатии кнопки.





Пожалуйста, предоставьте дополнительный код контекста. Опубликованного вами фрагмента XAML явно недостаточно для расследования. Рассмотрите возможность предоставления минимальный воспроизводимый пример.