連載:Silverlight 3実践プログラミング

LocalConnection APIと動的なスタイリング

シグマコンサルティング 菅原 英治
2010/02/09
Page1 Page2

サンプル・アプリのソース・コード解説

サンプル・アプリのソース・コード

 今回は、サンプル・アプリのソース・コードをあらかじめご用意させていただきました。次のリンクからファイルをダウンロードすることができます。

【ソース・コードのリンク】

 今回のサンプルのソリューション構成について、簡単に説明します。今回のサンプルは、次の画面のように3つのプロジェクトで構成されています。

ソリューションの構成(左:VB、右:C#)

 このうち重要なものは、メニューバー用のLocalMessageVB.MenuBar/LocalMessageCS.MenuBarプロジェクトと、サイドバー用のLocalMessageVB.SideBar/LocalMessageCS.SideBarプロジェクトです。そして、LocalMessageVB.Web/LocalMessageCS.Webサイトには、メニューバーとサイドバーの2つのSilverlightアプリをホストするindex.htmlファイルが定義されています。

メニューバー・アプリのコードの解説

 それでは、コードを解説します。まずは、メニューバー・アプリのLocalMessageVB.MenuBar/LocalMessageCS.MenuBarプロジェクトから解説しましょう。

画面側のXAMLコードの解説

 まず、画面側のソース・コード(XAMLコード)を解説しましょう。以下のコードをご覧ください。

<UserControl  ……(略)……>
  <UserControl.Resources>
    <!--ボタンのスタイルを定義-->
    <Style TargetType="Button" x:Key="Menu">
      <Setter Property="Width" Value="100"/>
      <Setter Property="Height" Value="30"/>
    </Style>
    <Style TargetType="Button" x:Key="MenuSelected">
      <Setter Property="Width" Value="100"/>
      <Setter Property="Height" Value="30"/>
      <Setter Property="Background" Value="RED"/>
    </Style>
  </UserControl.Resources>
  <Grid x:Name="LayoutRoot">
    <!-- メニューバーを定義 -->
    <StackPanel x:Name="Menu" Orientation="Horizontal">
      ……(略)……
    </StackPanel>
  </Grid>
</UserControl>
MainPage.xamlファイルのXAMLコード

 太字で示された、「x:Key="Menu"」、「x:Key="MenuSelected"」の2カ所がポイントです。これらは、ボタンに設定する選択時と未選択時のスタイル(=<Style>要素)の定義です。ボタンがクリックされた際に、定義したキー名を利用して、そのスタイルを動的に設定します。

 なお、LocalConnection APIを利用するという意味では、この部分に特に重要な個所はありません。

コード・ビハインドのコード解説

 続いて、コード・ビハインドのコードを解説します。以下のコードをご覧ください。

Imports System.Windows.Messaging

Partial Public Class MainPage
    Inherits UserControl

  ' メッセージ送信インスタンス
  Dim messageSender As New LocalMessageSender("receiver1")

  ' コンストラクタ
  Public Sub New()
    InitializeComponent()
  End Sub

  ' メニュー・クリック時のイベント・ハンドラ
  Private Sub Menu_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

    ' メッセージ送信インスタンスで、クリックされたボタンの
    ' 名前をメッセージとして送信する
    messageSender.SendAsync(CType(sender, Button).Name)

    ' 選択状態のスタイルを設定
    SetSelectedStyle(CType(sender, Button))
  End Sub

  ' 選択状態のスタイルを設定
  Private Sub SetSelectedStyle(ByVal button As Button)

    For Each b As Button In Menu.Children

      ' ボタンに対するスタイルのキー名を決定する
      Dim styleKey As String = "Menu"
      If b Is button Then
        styleKey = "MenuSelected"
      End If

      ' 動的にスタイルを設定する
      b.Style = CType(Me.Resources(styleKey), Style)
    Next

  End Sub

End Class
using System.Windows.Messaging;

namespace LocalMessageCS.MenuBar
{
  public partial class MainPage : UserControl
  {
    // メッセージ送信インスタンス
    LocalMessageSender messageSender =
      new LocalMessageSender("receiver1");

    // コンストラクタ
    public MainPage()
    {
      InitializeComponent();
    }

    // メニュー・クリック時のイベント・ハンドラ
    private void Menu_Click(object sender, RoutedEventArgs e)
    {
      // メッセージ送信インスタンスで、クリックされたボタンの
      // 名前をメッセージとして送信する
      messageSender.SendAsync((sender as Button).Name);

      // 選択状態のスタイルを設定する
      SetSelectedStyle(sender as Button);
    }

    // 選択状態のスタイルを設定
    private void SetSelectedStyle(Button button)
    {
      foreach (Button b in Menu.Children)
      {
        // ボタンに対するスタイルのキー名を決定する
        string styleKey = "Menu";
        if (b == button)
          styleKey = "MenuSelected";

        // 動的にスタイルを設定する
        b.Style = this.Resources[styleKey] as Style;
      }
    }

  }
}
コード・ビハインドの処理(上:MainPage.xaml.vb、下:MainPage.xaml.cs)

 ポイントは、大きく2つです。第1にLocalMessageSenderクラスを利用したメッセージの送信処理、第2に動的にスタイルを設定する処理です。

 では、LocalMessageSenderクラスを利用したメッセージの送信処理から。

 ここで行いたいことは、メニューバー側のSilverlightアプリ上のどのボタンがクリックされたかを、サイドバー側のSilverlightに伝える(=送信する)ことです。それを行うためにLocalMessageSenderクラスを利用します。

 コード上では、LocalMessageSenderクラスを利用するため、まずSystem.Windows.Messaging名前空間をImport/usingしています。そして、LocalMessageSenderクラスのインスタンスを生成します。その際、LocalMessageSenderクラスのコンストラクタに、「receiver1」という文字列の引数を渡しています。送信側は、この名前で受信側を識別します。詳しくは受信側のコード解説で触れます。

 そして、LocalMessageSenderオブジェクトのSendAsyncメソッドを利用して、クリックされたボタンの名前を受信側に送信しています。また本稿では触れませんが、 LocalMessageSenderクラスには、SendCompletedイベントがあり、それをハンドルすることで送信後の処理も行えます。

 続いて、動的にスタイルを設定する処理です。

 ここでは、クリックされたボタンのスタイルを選択状態にし、それ以外を未選択状態にしたいわけです。画面側のXAMLコードの解説で述べたとおり、選択は「MenuSelected」、未選択は「Menu」というキー名で定義されています。

 そのキー名を利用し、クリックされたボタンかどうかを判定して、そのボタンのStyleプロパティに適切なスタイルを動的に設定しています。また、画面側のXAMLコードで<UserControl.Resources>要素により定義したスタイルには、「Me.Resources/this.Resources」というコードでアクセスできます。

 メニューバー・アプリのコード解説は以上です。続いて、サイドバー・アプリのコードを解説します。

サイドバー・アプリのコードの解説

 サイドバー・アプリ用のLocalMessageVB.SideBar/LocalMessageCS.SideBarプロジェクトを解説しましょう。画面側のXAMLコードについては特に解説することはありませんので割愛します。コード・ビハインド側のコードのみ解説します。

コード・ビハインドのコード解説

Imports System.Windows.Messaging

Partial Public Class MainPage
    Inherits UserControl

  'メッセージ受信インスタンス
  Dim messageReceiver As New LocalMessageReceiver("receiver1")

  ' コンストラクタ
  Public Sub New()
    InitializeComponent()

    ' メッセージ受信時のイベント・ハンドラを設定
    AddHandler messageReceiver.MessageReceived, _
      AddressOf messageReceiver_MessageReceived

    Try
      ' レシーバを受信待ちにする
      messageReceiver.Listen()
    Catch ex As ListenFailedException
      MessageBox.Show( _
        "レシーバ名が重複しています。", _
        "LocalMessageReceiver", _
        MessageBoxButton.OK)
    End Try

  End Sub

  ' メッセージ受信時
  Private Sub messageReceiver_MessageReceived(ByVal sender As Object, ByVal e As MessageReceivedEventArgs)
    ……(略)……
  End Sub

End Class
using System.Windows.Messaging;

namespace LocalMessageCS.SideBar
{
  public partial class MainPage : UserControl
  {
    // メッセージ受信インスタンス
    LocalMessageReceiver messageReceiver =
      new LocalMessageReceiver("receiver1");

    // コンストラクタ
    public MainPage()
    {
      InitializeComponent();

      // メッセージ受信時のイベント・ハンドラを設定
      messageReceiver.MessageReceived +=
        messageReceiver_MessageReceived;
      try
      {
        // レシーバを受信待ちにする
        messageReceiver.Listen();
      }
      catch (ListenFailedException)
      {
        MessageBox.Show(
          "レシーバ名が重複しています。",
          "LocalMessageReceiver",
          MessageBoxButton.OK);
      }
    }

    // メッセージ受信時
    void messageReceiver_MessageReceived(object sender, MessageReceivedEventArgs e)
    {
      ……(略)……
    }
  }
}
コード・ビハインドの処理(上:MainPage.xaml.vb、下:MainPage.xaml.cs)

 ポイントは、LocalMessageReceiverクラスを利用したメッセージの受信処理です。

 まず、LocalMessageReceiverクラスのインスタンスを生成します。このとき、コンストラクタに「receiver1」という文字列の引数を渡しています。これが受信側の名前となります。送信側は、受信側の名前で受信側を識別し、メッセージを送ります。

 受信側の名前には注意が必要です。Silverlightを実行しているコンピュータ上で、重複しない名前である必要があります。試しに、いまご覧になっているこのページを、新しいウィンドウで新しく開いてみてください(つまり同じページを2つ開く)。新しく開いたページでは、「レシーバ名が重複しています」とアラートが表示され、サイドバーが表示されません。従って、今回のサンプルのようなページを同時に複数表示する際には、1ページごとに重複しない名前を付ける何らかの仕組みが必要になるでしょう。

 また受信側の名前の適用範囲は、デフォルトでは、Silverlightコントロールがホストされたアプリケーション・ドメイン内となります。しかし、LocalMessageSenderクラスとLocalMessageReceiverクラスのそれぞれのコンストラクタに第2引数(例:ReceiverNameScope.Global)と第3引数(例:LocalMessageReceiver.AnyDomain)を指定することで、その適用範囲を異なるアプリケーション・ドメイン間にまで広げられます。

 LocalMessageReceiverオブジェクトのMessageReceivedイベントをハンドルすることで、メッセージを受信した際の処理を制御できます。

 最後にLocalMessageReceiverオブジェクトのListenメソッドで受信待ちにできます。受信側の名前が重複していると、このListenメソッドで先ほど説明した例外が発生するので注意が必要です。

 メッセージが送られてくるとMessageReceivedイベントが発生します。そのイベント・ハンドラの第2パラメータであるMessageReceivedEventArgsオブジェクトのMessageプロパティには、送信側から送られてきたメッセージ(このサンプルではメニューの名前)が格納されています。それを利用することで、送信側と受信側を連携させることができます。

まとめ

 本稿では、LocalConnection APIと動的なスタイリングについて、サンプルを示して解説しました。サンプルは、HTMLページ上に組み込んだ2つのSilverlightアプリが連携できることを示しました。それを実現するのがLocalConnection APIでした。

 LocalConnection APIは、あくまで1台のコンピュータ上で実行されているSilverlightアプリ間の通信でした。実際に利用する際には、送信側がLocalMessageSenderクラス、受信側がLocalMessageReceiverクラスを利用します。また、受信側の名前は、重複しない名前を付ける必要がありました。

 さらに、動的なスタイリングを利用する方法も解説しました。画面側のXAMLコードのリソースにスタイルを定義しておけば、そのスタイルを動的に何度も設定できることが分かりました。

 さて次回は、UI要素のプロパティのバインドを提供する「Element-to-Elementバインディング」と、複数のファイルに分割されたリソース・ディクショナリ(ResourceDictionary)を管理できる「マージされたリソース・ディクショナリ」について解説します。お楽しみに!End of Article

 

 INDEX
  連載:Silverlight 3実践プログラミング 
  LocalConnection APIと動的なスタイリング
    1.サンプルを動かしてみよう
  2.サンプル・アプリのソース・コード解説

インデックス・ページヘ  「Silverlight 3実践プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH