Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/25: Рейтинг темы: голосов - 25, средняя оценка - 4.76
44 / 43 / 7
Регистрация: 18.05.2010
Сообщений: 688
1
WPF

Обновление ListBox при биндинге данных

05.12.2018, 11:33. Показов 5220. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго всем дня!

Есть задача обновлять список на "морде" программы данными из фонового потока.
к Листбоксу прибиндена коллекция
XML
1
<ListBox Grid.Row="0" ItemsSource="{Binding QList}" Name="MainLIst">
В Датаконтексте

C#
1
2
3
4
5
6
7
8
9
10
private List<MessagesData> qList;
        public List<MessagesData> QList {
            get {
                return qList;
            }
            set {
                qList = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( "QList" ) );
            }
        }
Если добавлять в коллекцию новые элементы из конструктора Класса, являющегося DataContext для окна, то "морда" обновляется корректно, если же откуда угодно из другого места, то нет.

Сначала думал, что проблема в потоках.
Посему решил делать это используя диспетчер, но и это не помогло.
Просто создал таймер в основном потоке, который раз в секунду должен добавлять новую запись в список и это не работает.
Добавил в таймер работу через диспетчер и оно так же не работает.

Вот последний вариант кода:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public MainWindow() {
    InitializeComponent();
    DataContext = new MainController();
 
    TextFieldForAnswer.KeyDown += IsEnter;
}
 
public MainController() {
    dis = Application.Current.MainWindow.Dispatcher;
    // где-то тут создаётся фоновый поток со своей логикой
 
    QList = new List<MessagesData>();
    QList.Add( new MessagesData {
        Name = "",
        Message = "Начало работы сервера_"
    } );
    // Этот элемент в список добавляется корректно
 
    Timer t = new Timer( 2000 );
    t.Elapsed += CheckPull;
    t.AutoReset = true;
    t.Enabled = true;
    t.Start();
}
 
private void CheckPull(object sender, ElapsedEventArgs e) {
    Console.WriteLine( "Таймер" );
    try {
        QList.Add( new MessagesData {
            Name = "Таймер",
            Message = "Начало работы сервера_"
        });
        // этот не добавляется
        dis.BeginInvoke( (Action)(() => {
            QList.Add( new MessagesData {
                Name = "Таймер",
                Message = "Начало работы сервера_"
            } );
        }));
        // и этот не добавляется
    } catch (Exception ex) {
        MessageBox.Show( ex.ToString() );
    }
Честно признаться, идеи кончились.
Может кто-нибудь подсказать, что я делаю не так?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.12.2018, 11:33
Ответы с готовыми решениями:

DataTrigger: Path при биндинге не распознается
Добрый день! Есть ListView с ItemsSource=&quot;{Binding Path=FilesList, Mode=TwoWay}&quot; Пробую...

При биндинге ComboBox выводится не то значение
Доброго времени суток. У меня стоит задача вывести название марок автомобилей в ComboBox ...

Обновление данных в ListBox, или ComboBox
Здравствуйте, Есть некое устройство с которого приходит достаточно большой набор данных,...

Ошибка при биндинге элементов формы к значениям
Доброго времени суток, внезапно возникла не понятная ошибка. Есть форма, а ней есть элементы. Есть...

8
879 / 558 / 291
Регистрация: 21.11.2012
Сообщений: 1,553
05.12.2018, 13:07 2
1. ваш MainController должен реализовывать InotifyPropertyChanged
2. для того, чтобы интерфейс синхронно обновлялся с коллекцией, нужно использовать ObservableCollection

для вашего примера было бы примерно так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MainController : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;
     private ObservableCollection<MessagesData> qList; 
     
     public ObservableCollection<MessagesData> QList 
     { 
         get { return qList; }
         set { qList = value; OnPropertyChanged(); }
     }
 
     private void OnPropertyChanged([CallerMemberName]string propertyName = "")
     {
     if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
     }
 
}
0
44 / 43 / 7
Регистрация: 18.05.2010
Сообщений: 688
05.12.2018, 13:20  [ТС] 3
hamin, к сожалению это не работает.
Я не написал про INotifyPropertyChanged, потому что думал, что это очевидно.
Коллекцию же я менял с листа на ObservableCollection и обратно. Эффект один и тот же.

Обновление ситуации: после попытка обновить что-нибудь в окне, если коллекция уже изменена, ломлю исключение:
объект itemscontrol не соответствует своему источнику элементов
0
879 / 558 / 291
Регистрация: 21.11.2012
Сообщений: 1,553
05.12.2018, 13:44 4
к сожалению большого опыта использования потоков у меня нет, но предполагаю, что проблема в том, что объект коллекции и ее обновление происходят в разных потоках

p.s. тут поковырялся чуток и если создавать и обновлять коллекцию в одном потоке, то все прекрасно работает и листбокс обновляется в задержкой 2 сек
0
44 / 43 / 7
Регистрация: 18.05.2010
Сообщений: 688
05.12.2018, 13:48  [ТС] 5
hamin, это была моя первая мысль. В конце концов я создал новый проект и там повторил интерфейс и работу с ним, но избавился от потоков как таковых.
Простые строчные поля типа TextBlock обновляются прекрасно, листбокс же игнорируется.

В конце концов решил проблему самолично подписавшись на PropertyChanged и там вызываля у листбокса
C#
1
...Items.Refresh();
Но мне кажется это каким-то адовым костылём
0
879 / 558 / 291
Регистрация: 21.11.2012
Сообщений: 1,553
05.12.2018, 13:53 6
Лучший ответ Сообщение было отмечено NapalmRain как решение

Решение

NapalmRain,
Вложения
Тип файла: rar WpfApp1.rar (222.7 Кб, 68 просмотров)
1
44 / 43 / 7
Регистрация: 18.05.2010
Сообщений: 688
05.12.2018, 14:20  [ТС] 7
hamin, Благодарю!
Разобрался в чём была причина.

На самом деле намудрил с потоками.
Всё дело в невнимательности.

Если вдруг у кого-то будет подобные проблемы, вот в чём косяк был у меня:
Коллекция действительно должна быть ObservableCollection, но менять её надо обязательно в текущем потоке, например через диспетчер окна.

Я же в пылу поиска ошибки удалил этот кусок и менял в фоновом потоке, из-за чего и ловил кучу ошибок. А когда переписал всё с нуля ObservableCollection уже не использовал, так как убедил себя в том, что разницы нет
1
Модератор
Эксперт .NET
15464 / 10710 / 2786
Регистрация: 21.04.2018
Сообщений: 31,529
Записей в блоге: 2
05.12.2018, 14:20 8
Цитата Сообщение от NapalmRain Посмотреть сообщение
конце концов я создал новый проект и там повторил интерфейс и работу с ним, но избавился от потоков как таковых.
Простые строчные поля типа TextBlock обновляются прекрасно, листбокс же игнорируется.
В конце концов решил проблему самолично подписавшись на PropertyChanged и там вызываля у листбокса
Если Вы меняете количественно коллекцию источника ListBox, то эта коллекция должна поддерживать интерфейс INCC (не путать с INPC). List - этот интерфейс не поддерживает, также List не относится к потокобезопасным коллекциям. Обновление изменение List должно происходить в одном потоке.
Из простых коллекций INCC поддерживает ObservableCollection.
1
44 / 43 / 7
Регистрация: 18.05.2010
Сообщений: 688
05.12.2018, 14:40  [ТС] 9
Элд Хасп, Благодарю, полезно
0
05.12.2018, 14:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.12.2018, 14:40
Помогаю со студенческими работами здесь

Не работает преобразование значений при биндинге (IValueConverter)
&lt;Button Click=&quot;btnMinimize_Click&quot; Cursor=&quot;Hand&quot; Height=&quot;10&quot; Margin=&quot;5,0,0,0&quot;...

Плавное движение слайдера при TwoWay биндинге WPF
Я использую TwoWay биндинг для привязки данных к слайдерам. Это приводит к небольшой проблеме, а...

При копирование одинаковых данных меж ListBox, проверять и выдавать сообщение о совпадении данных
У меня есть 2 компонента ListBox, и кнопка для копирования с 1-го ListBox во 2-й, и так условие...

Обновление данных в модели Linq to SQL при обновлении данных в БД
Подскажите новичку. Есть база данных, в приложении настроена работа с БД с помощью Linq to SQL. Из...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru