Я передаю IEnumerable Collection в WPF DataGrid через свойство DataGrid.ItemSource. Но он не обновляет DataGrid, когда я пытаюсь изменить элементы коллекции в коде. Почему?WPF DataGrid.ItemSource
ответ
Для привязки к типу, который реализует интерфейс INotifyCollectionChanged, необходимо, чтобы он передавал события, которые может использовать привязка данных для мониторинга при добавлении или удалении элементов. Лучший тип для этого в WPF является ObservableCollection <>, который имеет конструктор, который будет принимать ваш IEnumerable:
ObservableCollection<string> collection = new ObservableCollection<string>(iEnumerableobject);
dataGrid.ItemSource = collection;
collection.Add("Wibble");
обновит правильно.
От комментариев к другому ответу, похоже, что вам нужно вызвать вызов добавления из потока пользовательского интерфейса. Не зная ваш код более подробно я не знаю, почему вы должны сделать это, но давайте предположим, что вы получаете данные от службы в фоновом режиме:
private ObservableCollection<string> collection;
public void SetupBindings()
{
collection = new ObservableCollection<string>(iEnumerableobject);
dataGrid.ItemSource = collection;
//off the top of my head, so I may have this line wrong
ThreadPool.Queue(new ThreadWorkerItem(GetDataFromService));
}
public void GetDataFromService(object o)
{
string newValue = _service.GetData();
//if you try a call add here you will throw an exception
//because you are not in the same thread that created the control
//collection.Add(newValue);
//instead you need to invoke on the Ui dispatcher
if(Dispather.CurrentDispatcher.Thread != Thread.CurrentThread)
{
Dispatcher.CurrentDispatcher.Invoke(() => AddValue(newValue));
}
}
public void AddValue(string value)
{
//because this method was called through the dispatcher we can now add the item
collection.Add(value);
}
Как я говорю, я не есть IDE для передачи, поэтому это, вероятно, не будет компилироваться, но укажет вам в правильном направлении.
В зависимости от конкретной задачи, которую вы выполняете в фоновом режиме, могут быть лучшие способы сделать это. Мой пример выше был бы намного проще реализовать с использованием backgroundworker, поэтому вы можете также прочитать об этом.
Вместо этого вам необходимо использовать ObservableCollection. (Или сделать свой собственный класс обручи сбора и реализации INotifyPropertyChanged интерфейс)
Когда я пытаюсь внести изменения в сборку, VS говорит: Этот тип CollectionView не поддерживает изменяется на SourceCollection из потока, отличного от потока Dispatcher. – Agzam
Когда коллекция привязана к графическому интерфейсу, вы можете вносить изменения в коллекцию из основного потока графического интерфейса. Вы можете сделать это, вызвав Invoke на диспетчере форм. Сделайте, если (Dispather.CurrentDispatcher.Thread! = Thread.CurrentThread) {и затем вызовите Dispatcher.CurrentDispatcher.Invoke (и передайте делегат вашему методу) См. Здесь: http://msdn.microsoft.com/en-us/ library/system.windows.threading.dispatcher.invoke.aspx –
Вам нужно сделать все свои обновления в потоке пользовательского интерфейса, так как WPF поддерживает только модификации элементов управления из потока, на котором они были созданы. – Andy
Вы можете также использовать коллекцию, которая реализует интерфейс INotifyCollectionChanged, если вы не можете использовать ObservableCollection по какой-то причине ...
+1 за что а не только для использования «Wibble» в ответе. Молодец, я говорю! , , , и да, я чувствую себя немного странно сегодня днем. , , –
Я изменился на ObservableCollection, но он все равно не имеет значения. Он показывает правильные данные при первом запуске программы, но никогда не обновляет Grid после этого ... Я делаю что-то неправильно – Agzam