【VSTO+WPF】カスタムタスクペインのサンプル

こんにちは、こだかです。

例によってMSONの為にVSTO(Visual Studio Tools For Office SE)のデモを作成中なのですが、今回はWPFとの連携をポストします。
カスタムタスクペインにWPFコントロールを重ねたいのですが直接は出来ません。
したがって、別途WPFのユーザーコントロールを作成し、カスタムタスクペインにElementHostを使用してその上にホストする形をとります。

WPF側も、ただコントロールを重ねただけでは面白くありませんので、例によって4TravelさんのREST形式のWebサービスをバインドし画面表示してみます。
仕様:https://apiblog.kakaku.com/4travelSearchPictureV1.0.html
例:https://api.4travel.jp/Ver1/SearchPicture.php?model=cybershot&max=3

手順
1.ExcelAddInを新規作成し、UserControlを追加する。
2.[ファイル]⇒「新しいプロジェクトの追加より」CustomControlLibkary(WPF)のライブラリを新規作成し、ExcelAddIn側で参照の追加を行う
3.2に下記のXAML(UserControl1.xaml)をペーストする
4.1のプロジェクトにWindowsFormsIntegration、PresentationCore、PresentationFramework、WindowsBaseを参照追加し、 下記のコード(UserControl1.cs、ThisAddIn.cs)をペーストする
5.ビルドする

※プロジェクト名、UserControl名に注意して下さい。

実行例です。

 これで、ExcelのカスタムタスクペインにWPFがホストされたわけですが、Excelのシートとの値の連携には注意が必要です。

サンプルは以下にホストしておきました。
https://kodaka.info/mson/C3/Demo2.zip

こだかたろう

UserControl1.cs--------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Integration;

namespace ExcelAddIn1
{
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        private void UserControl1_Load(object sender, EventArgs e)
        {
            ElementHost ehost = new ElementHost();
            ehost.Dock = DockStyle.Fill;
            CustomControlLibrary1.UserControl1 myControl = new CustomControlLibrary1.UserControl1();
            ehost.Child = myControl;
            this.Controls.Add(ehost);
        }
    }
}

ThisAddIn.cs--------------------------------------------------------------------------------------------------
using System;
using System.Windows.Forms;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;

namespace ExcelAddIn1
{
    public partial class ThisAddIn
    {
        public Microsoft.Office.Tools.CustomTaskPane myTaskpane;
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            #region VSTO で生成されたコード

            this.Application = (Excel.Application)Microsoft.Office.Tools.Excel.ExcelLocale1033Proxy.Wrap(typeof(Excel.Application), this.Application);

            #endregion
            UserControl1 myControl = new UserControl1();
            myTaskpane = this.CustomTaskPanes.Add(myControl, "Demo");
            myTaskpane.Visible = true;
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO で生成されたコード

        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }
}

UserControl1.xaml-----------------------------------------------------------------------------------------------
<UserControl x:Class="CustomControlLibrary1.UserControl1"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <UserControl.Resources>
    <XmlDataProvider x:Key="traveldata"
                     Source="https://api.4travel.jp/Ver1/SearchPicture.php?model=cybershot"
                     XPath="results" />
    <DataTemplate x:Key="ListItemTemplate">
      <Border BorderBrush="Black" BorderThickness="2" CornerRadius="5" Margin="3">
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="200" />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="150" />
          </Grid.RowDefinitions>
          <Border Background="LightBlue" BorderBrush="Black" BorderThickness="1"
                  CornerRadius="5" Margin="3" >
            <Image Source="{Binding XPath=picturl}" Grid.Column="0" />
          </Border>
          <TextBlock Text="{Binding XPath=comment}"  Grid.Column="1" TextWrapping="Wrap" Name="Comment"/>
        </Grid>
      </Border>
    </DataTemplate>
  </UserControl.Resources>
  <Grid DataContext="{Binding Source={StaticResource traveldata}, XPath=pictinfo/item}">
    <ListBox Margin="6,5,8,9" Name="listBox1" ItemsSource="{Binding}" ItemTemplate="{StaticResource ListItemTemplate}" IsSynchronizedWithCurrentItem="True"/>
  </Grid>
</UserControl>