Okay, now I'm really going to show my age...  If you're an old fart like me you remember the classic Cracker Jack commericals featuring character actor Jack Gilford where he succumbs to pressure from little kids to share his Cracker Jacks and the tag line was "Sharing...".

Okay so you don't remember huh?  Anyway...the point of all of this is to talk about what else...sharing.  Specifically I want to talk about a Crossbow scenario where you may have a Windows Forms application that contains multiple ElementHost controls that each contain some WPF content and you want to use shared resources such as styles.

So here's the deal...In a standard WPF application you usually hang resources off of some parent element and in doing so, child element will inherit these resources.  For example, say that we want all Labels in a WPF application to have a certain look.  To acheive this we would do something like this:

<Window x:Class="WindowsApplication160.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowsApplication160" Height="300" Width="300"
Loaded="WindowLoaded"
    >
   <
StackPanel Name="sp1">
       <
StackPanel.Resources>
          <
Style TargetType="{x:Type Label}">
            <
Setter Property="FontSize" Value="14"/>
            <
Setter Property="FontWeight" Value="Bold"/>
         </
Style>
      </
StackPanel.Resources>
      <
Label>Hello</Label>
      <
Label>Goodbye</Label>
   </
StackPanel>
</
Window>

This will define the style for all Labels that are children of the StackPanel.  So all Labels that are added to the StackPanel will all inherit the style so that they all look the same.

Yeah, so...  Well the issue here is that say we have a Windows Forms application that contains some WPF content and you want to be able to create "global" styles for your elements.  Furthermore, you may have multiple instances of this or other WPF content spread across your Windows Forms application and you want them to all share common styles.  How do you do it?  The problem is that you don't have the ability to have application level XAML file (MyApp.xaml) where you could define global styles.

Well, it's really not difficult, you just have to know how to wire it all up.  So here's the deal... What you need to do is simply create a global ResourceDictionary to hang your global styles off of and then point all of your hosted WPF content to that ResourceDictionary.

Let's take a look at this in more detail.  Say we have a WPF UserControl that consists of multiple Labels.  (Yeah, I know...it's totally contrived and you would never build something so stupid, but bear with me it's just for illustrative purposes).  So the XAML for your UserControl may look something like:

<UserControl x:Class="GlobalStyleSample.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <
StackPanel Name="stackPanel1">
      <
Label>Label1</Label>
      <
Label>Label2</Label>
      <
Label>Label3</Label>
      <
Label>Label4</Label>
   </
StackPanel>
</
UserControl>

Now suppose that we want to host this content on a Windows Form form multiple times and we want to globally define how the labels in the UserControls should look and we want each instance of the UserControl to have the same look.

So let's host two instances of the UserControl on a Windows Form form using a SplitContainer to separate the two.  To do this, we need to first create the form and then drop a SplitContainer on the form.  Then we will put two ElementHost controls (one on each SplitterPanel).  Now, to make this easy for us to do, we're going to put the ElementHost control onto our Toolbox so that it will be easier for us to work at design time.

To do this, right-click on the ToolBox and pick 'Choose Items...'

Then you will see the 'Choose Toolbox Items' dialog box.  Here you will need to click the 'Browse' button to find the WindowsFormsIntegration dll that contains ElementHost.

 

Assuming that you are using the Feb CTP of Crossbow, you will find the dll in the Cider directory.

Next you will see the ElementHost control in the 'Choose Toolbox Items' dialog box.  Check the check box for the ElementHost control and click the OK button.

Now you should see the ElementHost control in the Toolbox.

Whew, you probably already knew how to do that anyway, but what the hell...

Now that we have the ElementHost control on our Toolbox, let's put this thing together.  Let's drop a SplitContainer on our Form.

Next we will put an ElementHost control on each of the panels of the SplitContainer.  Just drag and drop an ElementHost on each from the Toolbox.  Now, you will notice that the ElementHost gets rendered with its background color the same as the panels and without any borders.  This makes it look as though it's invisible once it is not selected.  If it bugs you that you cannot see the ElementHost when it is not selected, just set its background color to something else. 

Okay, next lets select each ElementHost control and Dock Fill them so that they take up all the real estate of each panel.  Now we can put our WPF UserControls on the form by hosting them in each ElementHost.  Let's do this by going to the code behind in say the Form_Load event handler to do this.

private void Form1_Load(object sender, EventArgs e)
{
   UserControl1 uc1 = new UserControl1();
   this.elementHost1.Controls.Add(uc1);
   UserControl1 uc2 = new UserControl1();
   this.elementHost2.Controls.Add(uc2);
}

Run the app and it should look something like:

Now we want to introduce our global Label style so that both instances of the UserControl uses the style for all of the labels.  We do this by creating a global ResourceDictionary and adding a style to it.

public partial class Form1 : Form
{
   private ResourceDictionary rd;
   public Form1()
   {
      InitializeComponent();

      rd =
new ResourceDictionary();

      Style myLabelStyle = new Style(typeof(System.Windows.Controls.Label));
      Setter fontSize = new Setter(System.Windows.Controls.Label.FontSizeProperty, 14.0);
      
Setter fontWeght = new Setter(System.Windows.Controls.Label.FontWeightProperty, FontWeights.Bold);

      myLabelStyle.Setters.Add(fontSize);
      myLabelStyle.Setters.Add(fontWeght);

      rd.Add(
typeof(System.Windows.Controls.Label), myLabelStyle);
}

Now we just need to point our UserControls to the ResourceDictionary object:

private void Form1_Load(object sender, EventArgs e)
{
      UserControl1 uc1 = new UserControl1();
      this.elementHost1.Controls.Add(uc1);
      UserControl1 uc2 = new UserControl1();
      this.elementHost2.Controls.Add(uc2);

      uc1.Resources = uc2.Resources = rd;
}

Let's run the app and see what happens now...

Sweet!  Now all of the WPF labels in our Windows Forms application share the same style.

Okay, I bet you are saying: "Hey, you could've just added that style to the definition of the UserControl in XAML and each instance of the UserControl in the app would share the Label's style".  Yep, in this particular case you're right.  However, what if the two instances of the UserControl were in fact two different UserControls for example.  In that case, I would have had to define the style in both XAML files.  This way I only have to define the style once in code behind and wire-up any WPF content to that style.