2009-06-11 3 views
0

Я передаю IEnumerable Collection в WPF DataGrid через свойство DataGrid.ItemSource. Но он не обновляет DataGrid, когда я пытаюсь изменить элементы коллекции в коде. Почему?WPF DataGrid.ItemSource

ответ

3

Для привязки к типу, который реализует интерфейс 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, поэтому вы можете также прочитать об этом.

+0

+1 за что а не только для использования «Wibble» в ответе. Молодец, я говорю! , , , и да, я чувствую себя немного странно сегодня днем. , , –

+0

Я изменился на ObservableCollection, но он все равно не имеет значения. Он показывает правильные данные при первом запуске программы, но никогда не обновляет Grid после этого ... Я делаю что-то неправильно – Agzam

1

Вместо этого вам необходимо использовать ObservableCollection. (Или сделать свой собственный класс обручи сбора и реализации INotifyPropertyChanged интерфейс)

+0

Когда я пытаюсь внести изменения в сборку, VS говорит: Этот тип CollectionView не поддерживает изменяется на SourceCollection из потока, отличного от потока Dispatcher. – Agzam

+0

Когда коллекция привязана к графическому интерфейсу, вы можете вносить изменения в коллекцию из основного потока графического интерфейса. Вы можете сделать это, вызвав Invoke на диспетчере форм. Сделайте, если (Dispather.CurrentDispatcher.Thread! = Thread.CurrentThread) {и затем вызовите Dispatcher.CurrentDispatcher.Invoke (и передайте делегат вашему методу) См. Здесь: http://msdn.microsoft.com/en-us/ library/system.windows.threading.dispatcher.invoke.aspx –

+0

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

0

Вы можете также использовать коллекцию, которая реализует интерфейс INotifyCollectionChanged, если вы не можете использовать ObservableCollection по какой-то причине ...