Reputation: 6552
Can't seem to get an ObservableCollection to update. The TreeView shows empty. Error: this type of collectionview does not support changes to its sourcecollection from a thread differentfrom the dispatcher thread.
Class level var
public ObservableCollection<TSItem> tsItems { get; set; }
Initialize Components
tsItems = new ObservableCollection<TSItem>();
bwRun.DoWork += bwRun_DoWork;
InitializeComponent();
tvTest.ItemsSource = tsItems;
from the background worker I use the following method to add to the collection
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>
Upvotes: 1
Views: 1273
Reputation: 14334
You have to invoke back onto the UI thread before updating your observable collection.
As a shortcut to just get it working, consider Application.Dispatcher.Invoke
or BeginInvoke
.This requires a reference to PresentationCore
so may not be great for MVVM if you want to be super pure about it.
If you want to be purer one way or another, you need to do a bit more work. Most of this involves trapping the SynchronizationContext
of the UI thread.
SynchronizationContext
and forwards the events of an internal ObservableCollection
SynchronizationContext
in your constructor using SynchronizationContext.Current
. This only works if your constructor is accessed on the UI thread.SynchronizationContext
into every class that needs ones.Upvotes: 3
Reputation: 1170
You should dispatch changes to UI thread:
private void AddTreeViewItem(TSItem item)
{
Dispatcher.BeginInvoke(new Action(() => tsItems.Add(item)));
}
Upvotes: 3
Reputation: 2524
@Somedust is correct. I would also add that you say that you are updating the observable collection via the background worker. If you are doing that, you need to ensure that you are back on the UI thread when doing so.
Upvotes: 1