Programmatically Selecting an Item in a TreeView

Tuesday, July 22nd, 2008

WPF’s composition and visualization capabilities are incredible. As you can see from my QbDirectoryViz post, it takes very little to visualize data using WPF. I believe the capabilities gained far outweigh the drawbacks. One of the drawbacks happens to be the programmatic selection of an item in a databound TreeView.

Background
In WinForms, the TreeView must be manually built out of TreeNodes which forces the developer to put their code in the UI. In WPF you have two options: either use the similar kludgy UI development technique and build your TreeView out of TreeViewItems, or use the more powerful technique of templates and databinding. The latter has the benefit of keeping data and logic separate from the UI as well as providing the foundation for easy visualization of the data.

Consider the following class:

public class SomeDataObject
{
private int _id;
private ObservableCollection<SomeDataObject> _children;

public SomeDataObject(int id)
{
this._id = id;
this._children = new ObservableCollection<SomeDataObject>();
}

public int Id
{
get { return this._id; }
}

public ObservableCollection<SomeDataObject> Children
{
get { return this._children; }
}
}

Create a few instances of this class and add them to an item’s children collection, and so on, and you have yourself a data structure in the form of a tree. Creating the UI is now just a matter of using a HierarchicalDataTemplate to visualize these objects:

<HierarchicalDataTemplate DataType=”{x:Type WpfTreeViewTricks:SomeDataObject}” ItemsSource=”{Binding Path=Children}”>
<StackPanel Orientation=”Horizontal”>
<TextBlock Text=”{Binding Path=Id}”/>
</StackPanel>
</HierarchicalDataTemplate>

The result is a just a simple visual tree that shows the id of each object. WPF will build the visual tree automatically and create a TreeViewItem for every instance of SomeDataObject. I suggest the following articles for more information on how the TreeView works:

TreeView Overview
Beatriz Costa TreeView Tricks Part 1
Beatriz Costa TreeView Tricks Part 2
Beatriz Costa TreeView Tricks Part 3

The Problem
The WPF TreeView exposes a SelectedItem property (of Type object) that is read only. This property gets updated when a user clicks on one of the TreeViewItems. The data object associated with the selected TreeViewItem is the object returned from the TreeView’s SelectedItem property, and the TreeViewItem’s IsSelected property changes to true. This is great for identifying the data object that is selected, but how do we get the TreeViewItem that is selected for this data-bound tree? Or better yet, how do we set the selected item of the tree programmatically if this property is read-only? The answer to the second question is simple: it is just a matter of setting the IsSelected property of the corresponding TreeViewItem to true, and the SelectedItem property of the TreeView is updated automatically. This means for any data object in the data tree, we must find the TreeViewItem that is representing this item and set its IsSelected property. At the time of writing, this is the only way to ‘set’ the SelectedItem of the TreeView. As it turns out, getting the UI element for an item in a ListView is easy, but getting the UI element for a TreeView is very hard (for three reasons described later).

Digging Deeper
To get the UI element (TreeViewItem) associated with an item in an ItemsControl (TreeView), the ItemContainerGenerator property can be used. All ItemsControls (Listbox, ListView, TreeView, even TreeViewItem) have the ItemContainerGenerator property, and getting the TreeViewItem from a data item is as simple as:

TreeViewItem treeViewItem = myTreeView.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

The Real Problems
The ItemContainerGenerator only works for a single list of items. Since a ListView’s items are in a flat list, the ListView can be used to get any of the UI elements representing any of its items. The TreeView’s children are hierarchical in nature, so only the first level of TreeViewItems can be retrieved using the TreeView’s ItemContainerGenerator. To get an item that is three levels deep the first level TreeViewItem must be retrieved and used (since it is an ItemsControl too) to get the second level TreeViewItem. Then this item must be used to finally get the third level TreeViewItem so we can set its IsSelected property to true. Having to iterate through the TreeViewItems is problem #1.

Problem #2 is the fact that TreeViewItems may not have been generated for children that are not expanded. This means we must expand every TreeViewItem just so we can navigate through them.

Problem #3 is the worst one of all: programmatically expanding a TreeViewItem is an asynchronous operation! Setting a the TreeViewItem’s IsExpanded property to true does not immediately generate the child UI elements. If the ItemContainerGenerator.ContainerFromItem(object item) method is called when these elements have not been generated, the return value is null (I’ve seen many people have this problem in the WPF forum).


The Solution

An extension method is used to simplify the usage of the solution.

public static void SelectItem(this TreeView treeView, object item)
{
ExpandAndSelectItem(treeView, item);
}

Using the extension method allows us to select an item in the WPF TreeView in the following way:

myTreeView.SelectItem(myItem);

Solving problem #1 requires iterating through all children at the top level first to see if any of them correspond to the item to select:

private static bool ExpandAndSelectItem(ItemsControl parentContainer, object itemToSelect)
{
foreach (Object item in parentContainer.Items)
{
TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

if (item == itemToSelect && currentContainer != null)
{
currentContainer.IsSelected = true;
currentContainer.BringIntoView();
currentContainer.Focus();

//the item was found
return true;
}
}

If no TreeViewItem is a match, then we must iterate through the children again to expand each one and iterate through its children:

foreach (Object item in parentContainer.Items)
{
TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

if (currentContainer != null && currentContainer.Items.Count > 0)
{
bool wasExpanded = currentContainer.IsExpanded;
currentContainer.IsExpanded = true;

Expanding the child solves problem #2, but to solve problem #3 (asynchronous generation of child UI elements) we must listen for an event from the ItemContainerGenerator that tells us the children have been generated. Since we want to execute the handler in line we can attach an anonymous delegate to the event so we can continue with the recursion. By storing the anonymous delegate in an EventHandler variable it allows us to remove the delegate when we are done (inside the delegate handler!).

if (currentContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
EventHandler eh = null;
eh = new EventHandler(delegate
{
if (currentContainer.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
if (ExpandAndSelectItem(currentContainer, itemToSelect) == false)
{
//The assumption is that code executing in this EventHandler is the result of the parent not
//being expanded since the containers were not generated.
//since the itemToSelect was not found in the children, collapse the parent since it was previously collapsed
currentContainer.IsExpanded = false;
}

//remove the StatusChanged event handler since we just handled it (we only needed it once)
currentContainer.ItemContainerGenerator.StatusChanged -= eh;
}
});
currentContainer.ItemContainerGenerator.StatusChanged += eh;
}
else //otherwise the containers have been generated, so look for item to select in the children
{
if (ExpandAndSelectItem(currentContainer, itemToSelect) == false)
{
//restore the current TreeViewItem’s expanded state
currentContainer.IsExpanded = wasExpanded;
}
else //otherwise the node was found and selected, so return true
{
return true;
}
}

I realize breaking the code up makes it difficult to see how it all works together, but hopefully it made for a better explanation of solving the three problems.

Attached is a project that demonstrates the solution by displaying a TreeView on the left and a ListView on the right. When an item is added it gets added to both the ListView’s collection and to a random location in the tree’s hierarchical collection. That way we can handle the selected event from the ListView and attempt to select that same item in the TreeView. Since the items are added randomly in the tree, more often than not selecting an item in the ListView will require the extension method to expand and dig through the TreeViewItems until the correct TreeViewitem is found. Try it out for yourself, it works!

You can thank Zhou Yong for coming up with a solution that I based my code off of here.

Some differences between this solution and others are that this one removes the attached event handler when done, and also collapses TreeViewItems to their original state. The downside of this solution (and all others that I know of) is that there is the potential that the entire tree is searched before the item is found. As long as your tree does not contain thousands of items it should not be an issue. Perhaps sometime in the future I will attempt to solve this problem.

The code is fully documented in the sample:
WpfTreeViewTricks.zip

Simple WPF Progress Window with Cancellation

Tuesday, July 22nd, 2008

Original Problem
Many times I have encountered a scenario where all I need to do is perform some small operation that takes a considerable amount of time. If I execute this operation on the UI thread, the UI will block until the operation is complete. Obviously this is not ideal. To address this need, the .NET engineers created the BackgroundWorker class in .NET 2.0. Its purpose is to execute a simple operation on a worker thread, and it does this very well. However, that is only half the battle. If an operation is happening in the background and the user needs to be notified of its progress, the BackgroundWorker must be wired up to some display that displays the progress. In WinForms, developers had many problems initially because they were trying to update controls from the worker thread. .NET 2.0 and later throws an exception if this cross-thread control updating is attempted since it is not allowed in either WinForms or WPF. If you did not know already, all UI controls can only be modified from the thread that created them (the UI thread). There are many examples scattered throughout the internet describing how a developer must ‘post’ the information back to the UI thread before updating a control, such as:

m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText), new object[]{”Text generated on non-UI thread.”});

WPF to the rescue
WPF has come to the rescue with its support for cross-thread property binding and notification. In other words, you can bind a progress bar’s current value to a property that gets changed on another thread. WPF will handle cross thread invoking automatically. This means it becomes very easy to design a WPF window that can not only display the progress of an operation, but also status text and other items that may be updated on the worker thread as an operation progresses, all without having to worry about invoking, callbacks, and threads.

Since most simple operations have the same pattern, a simple interface can be designed that simple operations can implement. We can then design a single WPF window that will display the progress of an operation by attaching to the interface rather than the simple operation:

Once the ProgressWindow and IProgressOperation classes are complete, many simple operations can be designed without having to worry about implementing another UI to display their progress. Here is an example of the IProgressOperation interface:

public interface IProgressOperation
{
int Total { get; }
int Current { get; }
void Start();
void CancelAsync();
event EventHandler ProgressChanged;
event EventHandler ProgressTotalChanged;
event EventHandler Complete;
}

Now we can implement a simple class that exports event logs, and implements this interface. Start() will start the BackgroundWorker, CancelAsync() will set a flag that the operation will check periodically, and the properties Total and Current provide the progress information needed for a progress display.

public void Start()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
public void CancelAsync()
{
this._isCancelationPending = true;
}
public int Current
{
get
{
return this._current;
}
private set
{
this._current = value;
OnProgressChanged(EventArgs.Empty);
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.Total = …

for (…)
{
//exit if the user cancels
if (this._isCancelationPending == true)
{
return;
}
this.Current++;
}
}

Now for the WPF window that will display this IProgressOperation. Since we will make the window implement INotifyPropertyChanged, when the ProgressChanged or ProgressTotalChanged events are raised from the background operation (and coming from a worker thread), we will just raise the events for WPF to update its bindings:

void _operation_ProgressChanged(object sender, EventArgs e)
{
OnPropertyChanged(”Current”);
}
void _operation_TotalChanged(object sender, EventArgs e)
{
OnPropertyChanged(”Total”);
}
public int Current
{
get
{
return this._operation.Current;
}
}
public int Total
{
get
{
return this._operation.Total;
}
}

Finally we have the XAML for the ProgressWindow that shows how it has both progress text and the Progressbar bound to the Current and Total properties that the window exposes to itself from the IProgressOperation.

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”32″/>
<RowDefinition Height=”*”/>
<RowDefinition Height=”42″/>
</Grid.RowDefinitions>
<StackPanel Grid.Row=”0″ Orientation=”Horizontal” HorizontalAlignment=”Center” VerticalAlignment=”Bottom”>
<TextBlock FontSize=”16″>Processing: </TextBlock>
<TextBlock FontSize=”16″ Margin=”5,0,0,0″ Text=”{Binding Path=Current, ElementName=Window, Mode=OneWay}”/>
<TextBlock FontSize=”16″ Margin=”5,0,5,0″>of</TextBlock>
<TextBlock FontSize=”16″ Text=”{Binding Path=Total, ElementName=Window, Mode=OneWay}”/>
</StackPanel>
<ProgressBar Grid.Row=”1″
Width=”200″
Height=”20″
Value=”{Binding Path=Current, ElementName=Window, Mode=OneWay}”
Minimum=”0″
Maximum=”{Binding Path=Total, ElementName=Window, Mode=OneWay}”></ProgressBar>
<StackPanel Grid.Row=”2″ Orientation=”Horizontal” HorizontalAlignment=”Center”>
<Button Margin=”6,6,6,6″ Width=”80″ Height=”30″ Click=”CancelClick”>Cancel</Button>
</StackPanel>
</Grid>

How do we start the operation and display the ProgressWindow? It is just a matter of creating a new ProgressWindow and passing in the IProgressOperation into its constructor:

ProgressWindow progressWindow = new ProgressWindow(new EventLogExporter());
progressWindow.ShowDialog();

The ProgressWindow will call the Start() method on the IProgressOperation once the window has completely loaded.

Keep in mind that this ProgressWindow is a very simple example demonstrating the power of WPF and binding. It can easily be extended to display many other items such as status text or other information, all using binding and not having to worry about invoking on the UI thread. You can also use the concepts provided in this article to design your own more powerful and customized ProgressWindow.

Sample: SimpleWPFProgressWindow

WPF Application Design and Architecture

Tuesday, July 22nd, 2008

As I have been studying WPF in the past several months, I have come to at least one conclusion: The power and flexibility of WPF comes with a subtle cost. This cost is that there are 100x more ways to design an application in WPF than there is in WinForms; therefore there are 100x more ways to shoot yourself in the foot. Fortunately, once one goes through the failures and learning cycle of WPF, it becomes much easier to design flexible and scalable applications in WPF than doing so in WinForms.

The purpose of this post is to illustrate the various ways a feature or WPF application can be designed.

This post:
-Provides a peek into the vast world of WPF application designs.
-Provides sample code for each design
-Is for beginner/intermediate level WPF application developers.
-Is not a ‘best practices’ guide, it just provides a set of examples to help readers understand how classes and interaction between objects can be designed.
-Is not a ‘How-To.’ The examples are extremely contrived and few WPF features are demonstrated.

Before continuing I suggest reading the following articles:
-Dr. WPF’s A Project Needs Structure
-Introduction to Model/View/ViewModel
-100 Model/View/ViewModels of Mt. Fuji
-Model-View-ViewModel pattern example
-ViewModel example
-Advantages and disadvantages of M-V-VM
-UML diagram of M-V-VM pattern
-WPF Patterns
-Dan Crevier’s DataModel-View-ViewModel Series
-DataModel and VIewModel

I also recommend studying the source and design of the following applications:
-Family.Show
-SceReader

If all of these concepts are new to you, it can be a bit overwhelming. It is a lot of information and concepts to absorb. Hopefully the samples provided in this post can make it easier to understand how these concepts can come into play in a real-world application. Four designs will be demonstrated, starting from an extremely simple design all the way to one that uses DataModel-View-ViewModel. Each sample has the same features to make it easier to follow along the evolution of the design.

The features that are demonstrated are as follows:
-Two buttons allow a user to find currently loaded assemblies and types
-A textbox allows the search to be filtered.
-The results are displayed in a listbox

Download the samples: WPFDesigns
I recommend browsing the source and following along as each sample and design is explained.

Design #1

For such a simple application, it really does not take much to implement the solution using just a window with some buttons and a ListBox on it. When a button is clicked, a handler can call a method and update the listbox’s ItemsSource directly.

public void ShowTypes_Click(object sender, RoutedEventArgs e)
{
this.ResultsListBox.ItemsSource = FindTypeNames();
}

1. A button is clicked and handled in Window1’s code behind.
2. The loaded types are retrieved.
3. The ListBox’s ItemsSource is updated

Design #2

In this sample the buttons and textbox are moved onto their own user control, while the ListBox is moved to its own user control as well. Breaking up a UI into modular components allows the UI to remain simple as many features are added, and forces the logic handling to be more modular as well.

<UserControl x:Class=”WpfDesigns2.Controls.OperationsUserControl”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
DataContext=”{Binding RelativeSource={RelativeSource Self}}”>
<Grid>
<StackPanel>
<Button Click=”ShowAssemblies_Click”>Show Assemblies</Button>
<Button Click=”ShowTypes_Click”>Show Types</Button>
<TextBlock>Match:</TextBlock>
<TextBox Width=”80″ Text=”{Binding Path=MatchText}”/>
</StackPanel>
</Grid>
</UserControl>

Now that each user control is handling its own events there needs to be some way to get the results from one user control to the other. Since the Window1 is hosting both user controls, in this sample we will make it listen to an operation complete event that contains the results, and then send those results to the user control with the ListBox so it can be updated.

1. The button click is handled in the Operations user control.
2. Using the MatchText variable and a ReflectionHelper object that exists in the Operations user control, the assemblies or types are retrieved.
3. The user control raises an event letting listeners know the results are complete.
4. Window1 handles the event and sends the results to the ReflectionResults property of the user control with the ListBox.
5. Since the ListBox is bound to the ReflectionResults dependency property, the ListBox UI is updated automatically.

Design #3

This sample takes the design a step further and breaks the UI from the logic. You can think of the user controls as the View and the logic as the Model. A manager called ApplicationManager was designed to contain all of the objects in the model. This manager is created in Window1’s XAML:

<ObjectDataProvider x:Key=”ApplicationManager” ObjectType=”{x:Type local:ApplicationManager}” />

Since Window1 contains the manager in its resources collection, it can pass on the manager’s child models to each respective user control:

<controls:OperationsUserControl
Grid.Column=”0″
x:Name=”OperationsControl”
DataContext=”{Binding Source={StaticResource ApplicationManager}, Path=ReflectionHelper}”/>
<controls:ReflectionResultsUserControl
Grid.Column=”1″
x:Name=”ReflectionDisplayControl”
DataContext=”{Binding Source={StaticResource ApplicationManager}, Path=ReflectionResults}”/>

Now each user control’s DataContext is set to an object from the Model layer, so that the UI elements can bind to a single model element. When the user control needs to get its model object, it can do so in the following way:

private ReflectionHelper ReflectionHelper
{
get
{
return this.DataContext as ReflectionHelper;
}
}

A button click in the handler is as easy as:

public void ShowTypes_Click(object sender, RoutedEventArgs e)
{
this.ReflectionHelper.FindTypes();
}

In this sample the ApplicationManager is handling listening for the results from one model and passing the data on to the results model. This separates the logic from the views. Since the ReflectionResultsUserControl is bound to the Results property on the results model, it gets updated automatically when the ApplicationManager updates the results model. At this stage the UserControls are doing virtually nothing and the model layer is doing all of the work (which is ideal).

1. The button click is handled in the OperationsUserControl.
2. The FindTypes or FindAssemblies method is called on the user control’s model element.
3. The reflection helper model element does some reflection work
4. When the work is complete an event is raised
5. The ApplicationManager listening for the event updates the ReflectionResults model element.
6. Since the ReflectionResultsUserControl’s ListBox is bound to the Results property of the ReflectionResults model element, the ListBox is updated automatically.

Design #4

At this point we have probably taken the samples as far as they need to go. However, to demonstrate one way the DataModel-View-ViewModel pattern can be implemented, sample #4 takes the design to the next level. Since the other DataModel-View-ViewModel articles already do a great job explaining the concepts, I will just describe the design for sample #4. Let’s start with the diagram:

1. Using a RoutedCommand the OperationsView handles the button click command.
2. The view calls into its view model to perform an operation.
3. Since the OperationsViewModel was storing the MatchText data, it can call into its model (ReflectionHelper) to find types or assemblies.
4. The ReflectionHelper model retrieves the matching types or assemblies.
5. The ReflectionHelper raises its operations complete event
6. The ApplicationManager handles the event and updates the ReflectionResults model.
7. The ReflectionResults model raises a results changed event
8. The ReflectionResultsVewModel handles the event and puts the results data into a format suitable for its view.
9. Since the ListBox in the ReflectionResultsView is bound to the ObservableCollection in its respective view model, the ListBox is updated automatically.

For such a small application this design is overkill. However, as applications grow in size and complexity, the DataModel-View-ViewModel pattern keeps the overall design simple and minimizes dependencies. It also has the added benefit of making all of the various modules much easier to test, which is obviously crucial to the success of any large piece of software.

One interesting aspect of the DM-V-VM is how well the view can be abstracted from the rest of the application. For example, in this sample a new class call ApplicationViewState was created to hold the view models that represent the views. A DataTemplate allows us to represent the view model in any way we want:

<DataTemplate DataType=”{x:Type viewModels:OperationsViewModel}”>
<!–Sets the view model as the data context–>
<views:OperationsView DataContext=”{Binding}” />
</DataTemplate>

In the main window a ContentPresenter is used to represent a ‘place holder’ for its content which is specified to be one of the view models:

<ContentPresenter
Grid.Column=”0″
Content=”{Binding Source={StaticResource ApplicationManager}, Path=ViewState.LeftSideView}”/>
<ContentPresenter
Grid.Column=”1″
Content=”{Binding Source={StaticResource ApplicationManager}, Path=ViewState.RightSideView}”/>

By swapping the view models in the ApplicationViewState, the views automatically follow their respective view model. This is a crude demonstration of a data driven UI.

Disclaimer: Design #4’s sample is not a perfect implementation of the DM-V-VM pattern. I have seen it implemented in various different ways. It usually depends on the requirements of the particular application. As far as I can tell there is also no difference between what people call a DataModel and a Model. Since many WPF applications work with a data layer of some sort such as a database, they call it the DataModel. In this last sample I could have easily just called the ReflectionHelper and ReflectionResults Models (I think I did a few times anyways).

A Word of Warning: If you are new to WPF, attempting to implement DM-V-VM for your application is extremely difficult. There are many ‘gotchas’ along the way that put major roadblocks in the way of solving problems. Most of these are WPF specific. Your best source of help is the MSDN WPF Forum.

In the real world, applications are usually a mix of all four of these designs. No single design fits every application. It is up to you to learn from your mistakes in order to learn how to design and develop simple, flexible, scalable applications. :) No matter how experienced you get, there is always more to learn!

Download the samples: WPFDesigns

All questions, comments, and criticism are welcome!

WPF Cross-Thread Collection Binding - Part 4 - The Grand Solution

Tuesday, July 22nd, 2008

The Grand Solution – Thread safe binding to a collection and properties that are modified from any thread.

History
-WPF supports cross thread property change notification.
-WPF does not support cross thread collection change notification.
-Part 1 introduced the ObservableBackgroundList<T> that allows cross thread collection change notification from a single worker thread.
-Part 2 described WPF’s lack of support for cross thread property change notification for items that are in the cross thread collection binding.
-Part 3 introduced a solution that allows cross thread property change notification from any thread for the items in the cross thread collection binding.

We are now ready to make the final leap and introduce a solution that supports binding to a collection that can be modified from any thread (including the UI thread). The class is called ObservableList<T>. Here is how to use it:

1. Pass in the UI’s Dispatcher to the constructor
2. Bind to the ObservableCollection property
3. Use the list from any thread by wrapping all list operations in a using block that utilizes the method AcquireLock.

The ObservableList is made thread-safe by acquiring a lock before accessing the list (including just reads). The AcquireLock method is the way to lock the list and prevent other threads from modifying the list while the list is being accessed by the thread owning the lock. Below is a screenshot of a sample application that demonstrates simulating a server that has many worker threads that update the collection and modify properties.

This is an example of how to wrap all list operations in a using block where _activeTasks is an ObservableList<Task>:

using (TimedLock timedLock = this._activeTasks.AcquireLock())
{
foreach (Task task in this._activeTasks)
{
task.PercentComplete = 100;
}
}

The TimedLock is an IDisposable class that locks on an object passed into its constructor and then unlocks when the TimedLock is disposed. ‘Using’ ensures that no matter what happens inside the using parenthesis, the IDisposable.Dispose() method will be called on the TimedLock, thus releasing the lock. If any single thread has acquired the TimedLock then all other threads will block (provided they follow the same pattern). Even the UI thread must acquire the lock before accessing the ObservableList (but WPF does not need to lock on the ObservableCollection). The TimedLock was taken from IanG’s blog and is nothing more than a lock with a timeout to help debugging scenarios.

Quiz for the experts: In the ObservableList<T> all change requests are always posted to the UI thread via the Dispatcher, even when the UI thread is the thread accessing the list. Why did I design it so the UI thread takes a performance hit and still posts change requests to itself? One might think that when the UI thread is executing, all change requests from other threads are automatically blocked until the UI is done, so it should be safe to update the list directly. This turns out to be false. I myself am not a threading guru, but if anyone gets the right answer you can wear that award :)

We now have solution with the following features:

Features
-Allows WPF to bind to a collection that is modified from any thread
-Allows WPF to bind to properties of items in the collection that are modified from any thread
-No lock required if used from a single worker thread
-Relatively simple (compared to some other attempts)
-Non-blocking

Downsides
-Requires two lists internally
-The ObservableCollection list should not be modified
-Disposable or DependencyObjects should not be used

Despite these negatives, the community now has a solution to suit developers’ WPF, binding, and multithreading needs.

Disclaimer: Although I spent a considerable amount of time studying and testing the design and concepts described in this series, as well as beating the heck out of the ObservableList<T> with a quad core CPU and 10+ threads each modifying the collection and properties at full speed, I am still human and this is just a blog post. Do your own research and testing, and as always, use at your own risk. I will keep this post updated if there are any issues. I personally believe we can put this topic to rest until WPF adds native support for all of these features.

UPDATE: Microsoft has recognized the property/collection change race condition bug and will fix it in a future version of the framework.

Download the Sample: MultithreadedObservableListSample