Last week I posted about how I was calling a Workflow library from an Avalon
(WPF) application. The Workflow library used DLINQ to query a SQL database.
Basically, I was trying to get cute with the CTPs. I ran into a problem with an
exception being thrown, "The calling thread may not access this object
because the object is owned by a different thread." Knowing this issue was
probably similar to having to update controls on the UI thread of a WinForms
application using
Control.Invoke or this.Invoke I went looking to do just that. However, the
WPF controls didn't have an Invoke method, neither did the "this pointer." Using
intellisense as my documentation, I found
Dispatcher.Invoke which allowed me to do roughly the same thing. So, the
Workflow is called and I pass a reference of the Avalon Window to the Workflow
so it can do a callback to the Avalon Window (via interface implementation). The
callback function name is Process(), and this function calls Dispatcher.Invoke
passing a delegate to the method that actually performs the databinding like so:
public
delegate void
BindDelegate(object
data);
public
void BindCustomerListBox(object
data) {
CustomerRecordCollection customers = (CustomerRecordCollection)data;
this.docPanelCustomers.DataContext = customers;
}
public
void Process(object
data) {
BindDelegate del = new
BindDelegate(this.BindCustomerListBox);
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
del, data);
}
The updated XAML from my last post is:
<Window x:Class="WindowsApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
Title="WindowsApplication1" Closed="Window_Closed" Width="499" Height="461">
<Window.Resources>
<DataTemplate x:Key="CustomerTemplate">
<DockPanel>
<TextBlock Width="300" Text="{Binding Path=CustomerID}" />
<TextBlock Width="300" Text="{Binding Path=CompanyName}" />
<TextBlock Width="300" Text="{Binding Path=NumOrders}"/>
</DockPanel>
</DataTemplate>
</Window.Resources>
<DockPanel x:Name="docPanelCustomers" LastChildFill="False" Width="Auto" Height="392">
<ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ItemTemplate="{StaticResource CustomerTemplate}" DockPanel.Dock="Bottom" Width="Auto" Height="267" VerticalAlignment="Stretch" />
<Button DockPanel.Dock="Top" x:Name="buttonGetCustomers" Click="buttonGetCustomers_Click">Run Workflow</Button>
</DockPanel>
</Window>
Result: worked like a champ!
