title: Using control defined in XAML in another thread
body: <p>I am playng around with the library found <a href="http://microsoftdwayneneed.codeplex.com/" rel="nofollow">here</a>, which is to help render the UI on multiple threads.  The sample works fine and does what it's supposed to but I wanted to modify it a little.</p>
  
  <p>In the sample, the visual element that is to be rendered on a separate thread is defined/created in the code behind.  Here is some of the sample code:</p>
  
  <p>XAML:</p>
  
  <pre><code>&lt;Window x:Class="VisualTargetDemo.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:Microsoft.DwayneNeed.Controls;assembly=Microsoft.DwayneNeed"
      Title="VisualTargetDemo"
      SizeToContent="WidthAndHeight"
      Loaded="OnLoaded"
      &gt;
    &lt;Grid&gt;
      &lt;Grid.ColumnDefinitions&gt;
        &lt;ColumnDefinition Width="*"/&gt;
        &lt;ColumnDefinition Width="*"/&gt;
        &lt;ColumnDefinition Width="*"/&gt;
      &lt;/Grid.ColumnDefinitions&gt;
      &lt;local:VisualWrapper Grid.Column="0" Width="200" Height="100" x:Name="Player1"/&gt;
      &lt;local:VisualWrapper Grid.Column="1" Width="200" Height="100" x:Name="Player2"/&gt;
      &lt;local:VisualWrapper Grid.Column="2" Width="200" Height="100" x:Name="Player3"/&gt;
    &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>Code-behind:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Data;
  using System.Windows.Documents;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  using System.Windows.Shapes;
  using System.Threading;
  using Microsoft.DwayneNeed.Controls;
  using Microsoft.DwayneNeed.Threading;
  
  namespace VisualTargetDemo
  {
      public partial class Window1 : System.Windows.Window
      {
          public Window1()
          {
              InitializeComponent();
          }
  
          private void OnLoaded(object sender, RoutedEventArgs e)
          {
              Player1.Child = CreateMediaElementOnWorkerThread();
              Player2.Child = CreateMediaElementOnWorkerThread();
              Player3.Child = CreateMediaElementOnWorkerThread();
          }
  
          private HostVisual CreateMediaElementOnWorkerThread()
          {
              // Create the HostVisual that will "contain" the VisualTarget
              // on the worker thread.
              HostVisual hostVisual = new HostVisual();
  
              // Spin up a worker thread, and pass it the HostVisual that it
              // should be part of.
              Thread thread = new Thread(new ParameterizedThreadStart(MediaWorkerThread));
              thread.SetApartmentState(ApartmentState.STA);
              thread.IsBackground = true;
              thread.Start(hostVisual);
  
              // Wait for the worker thread to spin up and create the VisualTarget.
              s_event.WaitOne();
  
              return hostVisual;
          }
  
          private FrameworkElement CreateMediaElement()
          {
              // Create a MediaElement, and give it some video content.
              MediaElement mediaElement = new MediaElement();
              mediaElement.BeginInit();
              mediaElement.Source = new Uri("http://download.microsoft.com/download/2/C/4/2C433161-F56C-4BAB-BBC5-B8C6F240AFCC/SL_0410_448x256_300kb_2passCBR.wmv?amp;clcid=0x409");
              mediaElement.Width = 200;
              mediaElement.Height = 100;
              mediaElement.EndInit();
  
              return mediaElement;
          }
  
          private void MediaWorkerThread(object arg)
          {
              // Create the VisualTargetPresentationSource and then signal the
              // calling thread, so that it can continue without waiting for us.
              HostVisual hostVisual = (HostVisual)arg;
              VisualTargetPresentationSource visualTargetPS = new VisualTargetPresentationSource(hostVisual);
              s_event.Set();
  
              // Create a MediaElement and use it as the root visual for the
              // VisualTarget.
              visualTargetPS.RootVisual = CreateMediaElement();
  
              // Run a dispatcher for this worker thread.  This is the central
              // processing loop for WPF.
              System.Windows.Threading.Dispatcher.Run();
          }
  
          private static AutoResetEvent s_event = new AutoResetEvent(false);
      }
  }
  </code></pre>
  
  <p><br/><br/>
  So OnLoaded creates and sets the Child property of the VisualWrapper.  What I would like to do is allow the user to define which control to assign to Child directly in the XAML, something like:</p>
  
  <pre><code>&lt;local:VisualWrapper Grid.Column="0" Width="200" Height="100" x:Name="Player1"/&gt;               
    &lt;local:VisualWrapper.ChildSource&gt;
      &lt;Button&gt;TEST&lt;/Button&gt;
    &lt;/local:VisualWrapper.ChildSource&gt;
  &lt;/View:VisualWrapper&gt;
  </code></pre>
  
  <p><br/><br/>
  The plan was to add a ChildSource DependencyProperty to the VisualWrapper class and whenever that property changes, recreate it's Child content.  The problem is that when I try to access the ChildSource control from within the VisualWrapper:</p>
  
  <pre><code>public FrameworkElement ChildSource
  {
      get { return (FrameworkElement)this.GetValue(ChildSourceProperty); }
      set { this.SetValue(ChildSourceProperty, value); }
  }
  </code></pre>
  
  <p>I get an error: "The calling thread cannot access this object because a different thread owns it.".  I can't get it to work and am wondering if it's even possible.</p>
  
  <p><br/><br/>
  I tried using the Dispatcher in the getter:</p>
  
  <pre><code>public FrameworkElement ChildSource
  {
      get { return (FrameworkElement)Dispatcher.Invoke((Delegate)GetValue(ChildSourceProperty)); }
      set { this.SetValue(ChildSourceProperty, value); }
  }
  </code></pre>
  
  <p>But that didn't work.  My feeling is that some Disaptcher.Invoke would be required but I am not sure where.</p>
  
  <p>Can what I am trying to do be done?</p>