Using WPF With VSTO & Office 2007

Hosting Windows Forms controls in Office 2007 Custom Task Pane's is pretty simple, as shown in this MSDN article.  I created a simple addin to display a list of image files in a given folder so that the user can double-click on the file name (in a ListBox) and insert the picture into the document.  With little effort it was simple to instead implement a WPF UserControl to spruce up the addin.  You can download the code here.

Document1 - Microsoft Word

 

You can host WPF Elements using the ElementHost control found in the WindowsFormsIntegration assemly that ships with the .NET 3.0 runtime.  The CustomTaskPane requires a Windows Forms UserControl, so I'm just adding the ElementHost control to a plain Windows Forms UserControl and then passing that UserControl to be created with the CustomTaskPane.

internal void AddTaskPane()

{

    ElementHost host = new ElementHost();

    browser = new ImageBrowserControl();

    host.Child = browser;

    host.Dock = DockStyle.Fill;

 

    browser.PictureSelected += ImageBrowserControl_PictureSelected;

 

    UserControl userControl = new UserControl();

    userControl.Controls.Add(host);

 

    pane = this.CustomTaskPanes.Add(userControl, "Image Browser");

 

    pane.Visible = true;

}

 

Inserting images into a Word document is just as simple, as shown in the following code snippet:

private void ImageBrowserControl_PictureSelected(Object sender, EventArgs<Picture> e)

{

    Object missing = System.Reflection.Missing.Value;

 

    Globals.ThisAddIn.Application.Selection.InlineShapes.AddPicture(

        e.Item.Filename, ref missing, ref missing, ref missing);

}

 

The EventArgs<T> class used in the previous handler is a nice trick to use in conjunction with EventHandler<T>.  A tip from Jean-Paul S. Boodhoo's Blog.

public class EventArgs<T> : EventArgs

{

    private T m_Item;

 

    public EventArgs(T item)

    {

        m_Item = item;

    }

 

    public T Item

    {

        get

        {

            return m_Item;

        }

    }

}

 

public event EventHandler<EventArgs<Picture>> PictureSelected;

 

To create  a Ribbon tab you define a set of XML.  The onAction on the button is an event that you can handle in your codebehind file.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">

  <ribbon>

    <tabs>

      <tab id="VSTOAddIns" label="Addins" >

        <group id="Group1" label="Helpers" visible ="1">

          <button id="ImageBrowser" label="Insert Image"

          onAction="ImageButtonClick"

          imageMso="ContentControlDate"/>

        </group>

      </tab>

    </tabs>

  </ribbon>

</customUI>

 

Handler for toggling showing / hiding the task pane:

public void ImageButtonClick(Office.IRibbonControl control)

{

    if (!m_ImagePaneExists)

    {

        Globals.ThisAddIn.AddTaskPane();

    }

    else

    {

        Globals.ThisAddIn.RemoveTaskPane();

    }

 

    m_ImagePaneExists = !m_ImagePaneExists;

}

 

 The WPF UserControl styles a simple Picture class, shown below:

public class Picture

{

    private FileInfo m_FileInfo;

 

    public Picture(String filename)

    {

        m_FileInfo = new FileInfo(filename);

    }

 

    public String Filename

    {

        get { return m_FileInfo.FullName; }

        set { m_FileInfo = new FileInfo(value); }

    }

 

    public String Name

    {

        get { return m_FileInfo.Name; }

    }

}

 

 DataTemplate for the Picture class:

<DataTemplate DataType="{x:Type local:Picture}">

  <StackPanel MinHeight="0px" MinWidth="0px" MaxHeight="150px" MaxWidth="150px" >

    <Image Stretch="UniformToFill" Source="{Binding Filename}" />

    <TextBlock Text="{Binding Name}"

              FontWeight="Bold"

              HorizontalAlignment="Center"

              />

  </StackPanel>

</DataTemplate>

 

The ListBox style is taken from my previous blog post on styling ListBoxItem's.

<Style TargetType="ListBoxItem">

  <Setter Property="Template">

    <Setter.Value>

      <ControlTemplate TargetType="ListBoxItem">

        <Border x:Name="ItemBorder"

                BorderBrush="Black"

                Background="LightGray"

                BorderThickness="2"

                CornerRadius="4"

                Margin="3"

                >

          <ContentPresenter Margin="2" />

        </Border>

        <ControlTemplate.Triggers>

          <Trigger Property="IsSelected" Value="True">

            <Setter TargetName="ItemBorder"

                    Property="BorderBrush"

                    Value="Red"

                    />

          </Trigger>

          <Trigger Property="IsMouseOver" Value="True">

            <Setter TargetName="ItemBorder"

                    Property="BorderBrush"

                    Value="Blue"

                    />

          </Trigger>

          <MultiTrigger>

            <MultiTrigger.Conditions>

              <Condition Property="IsMouseOver" Value="False" />

              <Condition Property="IsSelected" Value="False" />

            </MultiTrigger.Conditions>

            <Setter TargetName="ItemBorder"

                    Property="Opacity"

                    Value="0.50"

                    />

          </MultiTrigger>

        </ControlTemplate.Triggers>

      </ControlTemplate>

    </Setter.Value>

  </Setter>

</Style>

 

A couple things to remember when building Word Addins is that all Assembly's that you use need to be signed and granted full-trust by the .NET runtime for Word to load them.  Other than that creating Word Addins is pretty simple!

Published Tuesday, July 17, 2007 8:31 PM by Joe
Filed under: ,

Comments

# re: Using WPF With VSTO & Office 2007

Tuesday, August 28, 2007 7:25 PM by Keith Pelletier

Hey Joe... can you do this control in Excel? In particular, can you get your text box to have focus in Excel?

I implemented this in Word and all is good (actually, the Custom Task Pane never really gets focus if you look at Spy++)... but Word doesn't seem to care.

In Excel, this causes problems for me.

I click the search textbox and it appears to have focus... but, when I start typing, text goes into the active cell and not the textbox...

Do you have the same experience in Excel? Again, Word doesn't show this behavior. Thanks so much...

Keith Pelletier

kpelletier@elumindata.com

# re: Using WPF With VSTO & Office 2007

Wednesday, August 29, 2007 9:29 PM by Joe

Keith,

That seems like an interesting problem.  I'll try this in Excel this weekend and see what I come up with.

Joe

# re: Using WPF With VSTO & Office 2007

Thursday, August 30, 2007 9:31 AM by Keith Pelletier

Hey Joe... looking forward to seeing what you get. I had a friend try it with a different machine (to make sure it wasn't just me)... he had VS2008 B2 and Office 2007... he had the same issue I did with Excel. So, my feeling is this is a bug.

The WM_SETFOCUS never gets called unless you do a little trick with the Task Pane Menu.

It just seems to be a problem with ElementHost. Regular WinForm UserControls work... WebBrowser Control works... hell... the Flash OCX embedded works. Kinda sucks...

Best,

Keith

# Joe's Blog : WPF Interoperability with Windows Forms and Office 2007

PingBack from http://xamlcoder.com/cs/blogs/joe/archive/2007/09/03/wpf-interoperability-with-windows-forms-and-office-2007.aspx

# WPF Interoperability with Windows Forms and Office 2007 - Joe&#39;s Blog

PingBack from http://utahdnug.org/blogs/xamlcoder/archive/2007/09/03/wpf-interoperability-with-windows-forms-and-office-2007.aspx

Powered by Community Server (Non-Commercial Edition), by Telligent Systems