2013-12-02 2 views
0

Кажется, что не удалось обновить ObservableCollection. TreeView показывает пустой. Ошибка: этот тип коллекции не поддерживает изменения в его исходном наборе из потока, отличного от потока диспетчера.WPF ObservableCollection не обновляется?

уровня Класс вар

public ObservableCollection<TSItem> tsItems { get; set; } 

Инициализировать Компоненты

tsItems = new ObservableCollection<TSItem>(); 
bwRun.DoWork += bwRun_DoWork; 
InitializeComponent(); 
tvTest.ItemsSource = tsItems; 

от фона рабочего я использую следующий метод, чтобы добавить к коллекции

private void AddTreeViewItem(TSItem item) 
{ 
    tsItems.Add(item); 
} 

XAML

<TreeView x:Name="tvTest" HorizontalAlignment="Left" Height="249" Margin="140,36,0,0" VerticalAlignment="Top" Width="257"> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <Image Source="{Binding Icon}" /> 
        <TextBlock Text="{Binding Header}" /> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 
+1

Действительно ли вы начинаете свой рабочий стол? Я не смог воспроизвести вашу проблему. – Somedust

+0

да, обновленный пост. Рабочий запускается в событии Loaded. – Tsukasa

+0

tsItems должен быть общедоступным ... – Nahum

ответ

2

Вы должны направить изменения в UI потоке:

private void AddTreeViewItem(TSItem item) 
{ 
    Dispatcher.BeginInvoke(new Action(() => tsItems.Add(item))); 
} 
+0

Переключил TSItem в общедоступный класс вместе с созданием коллекции публичным и до сих пор не обновляет – Tsukasa

+0

С этим я получаю Должен создавать DependencySource в той же теме, что и DependencyObject – Tsukasa

+1

. Я верю, что эта ошибка как-то связана к созданию источника изображения. Если вы динамически создаете растровое изображение, вы должны его заморозить, вызвав метод Freeze(). http://msdn.microsoft.com/ru-ru/library/ms557735(v=vs.110).aspx – Somedust

0

@Somedust правильно. Я бы также добавил, что вы говорите, что обновляете наблюдаемую коллекцию с помощью рабочего фона. Если вы это делаете, вам нужно убедиться, что вы вернулись к потоку пользовательского интерфейса при этом.

+0

Есть ли способ обновить его, не входя в поток пользовательского интерфейса? Мне нужен пользователь, чтобы увидеть прогресс в TreeView, поскольку он работает?Должно ли это потребовать от меня создания рабочего для каждой задачи, а затем его полного обновления? – Tsukasa

+0

См. Мой обновленный ответ. – Somedust

1

У вас есть, чтобы вернуть обратно к пользовательскому интерфейсу перед обновлением наблюдаемой коллекции.

Как ярлык просто заставить его работать, рассмотрит Application.Dispatcher.Invoke или BeginInvoke .Это требует ссылка на PresentationCore поэтому не может быть большой для MVVM, если вы хотите быть сверхчистыми об этом.


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

  • Создать собственную реализацию INotifyCollectionChanged, которая надстроена в SynchronizationContext и перенаправляет события внутренней ObservableCollection
  • захватить SynchronizationContext в конструкторе с помощью SynchronizationContext.Current. Это работает, только если ваш конструктор обращается к потоку пользовательского интерфейса.
  • Передайте SynchronizationContext всем нуждающимся.
Смежные вопросы