I have a problem with cross-stream operations in C # / WPF / .NET 4.0.
Situation:
I need to create a tree of objects when the user clicks a button and then snaps to the tree. Since creation takes a lot of time (children are created recursively), I used Thread / BackgroundWorker / Task to prevent the user interface from freezing.
Problem:
I get a XamlParserException (I need to create a DependencySource in the same thread as DependencyObject) when binding to an object tree.
I understand the problem, but how can I fix it? I cannot create a tree of objects in the user interface thread because it freezes the user interface. But I also can not create a tree of objects in another thread, because then I can not bind to it.
Is there a way to "marshal" objects to a user interface thread?
Event handler code (executed in the user interface thread)
private void OnDiff(object sender, RoutedEventArgs e) { string path1 = this.Path1.Text; string path2 = this.Path2.Text; // Some simple UI updates. this.ProgressWindow.SetText(string.Format( "Comparing {0} with {1}...", path1, path2)); this.IsEnabled = false; this.ProgressWindow.Show(); this.ProgressWindow.Focus(); // The object tree to be created. Comparison comparison = null; Task.Factory.StartNew(() => { // May take a few seconds... comparison = new Comparison(path1, path2); }).ContinueWith(x => { // Again some simple UI updates. this.ProgressWindow.SetText("Updating user interface..."); this.DiffView.Items.Clear(); this.Output.Items.Clear(); foreach (Comparison diffItem in comparison.Items) { this.DiffView.Items.Add(diffItem); this.AddOutput(diffItem); } this.Output.Visibility = Visibility.Visible; this.IsEnabled = true; this.ProgressWindow.Hide(); }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); }
Binding example
<DataGrid.Columns> <DataGridTemplateColumn CellTemplate="{StaticResource DataGridIconCellTemplate}"/> <DataGridTextColumn Header="Status" Binding="{Binding Path=ItemStatus}"/> <DataGridTextColumn Header="Type" Binding="{Binding Path=ItemType}"/> <DataGridTextColumn Header="Path" Binding="{Binding Path=RelativePath}" Width="*"/> </DataGrid.Columns>
Hello Dominik
source share