SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

WPFで、マウスポインタを外すと自動的に隠れるウィンドウを実装する

WPFでツールウィンドウを作成する - AutoHide編

手順1 プロジェクトの作成

  1. 「WpfApplicationSubWindow1」という名前のWPFアプリケーションを作成します。
     
  2. カスタムコントロールを追加します。
    ソリューションエクスプローラ内の[WpfApplicationSubWindow1]プロジェクトを右クリックし、[追加]-[新しい項目]を選択して、[新しい項目の追加]ダイアログボックスを表示します。
    テンプレートで[ユーザーコントロール(WPF)]を選択し、ファイル名を「SubWindows」にして追加します。
    「SubWindows.cs」と同時に、「Themes」フォルダ内に「Generic.xaml」が生成されます。コントロールの外観はこの「Generic.xaml」内で記述します。
     
  3. ツールウィンドウ内に表示するためのページを作っておきます。
    先程と同様に[新しい項目の追加]ダイアログボックスを開き、テンプレートで[ページ(WPF)]を選択し、「Page1.xaml」という名前で追加します。ページの内容は適当に編集しておいてください。
     
  4. 表示用のアイコンを追加します。
    プロジェクトの「Image」フォルダ内に「arrow.PNG」「btnAutoHide.PNG」「btnClose.PNG」「btnMenu.PNG」を追加します。
    最初のアイコンは、左右下のタブの表示に使います。後の3つのアイコンは、ツールウィンドウのタイトルバー右端に表示されます。アイコンファイルは適当に用意してください。
     
  5. 最後に、「TitleAndPage.cs」を作成します。
    ソリューションエクスプローラ内のプロジェクトを右クリックして、[追加]-[クラス]を選択し、ファイル名を「TitleAndPage.cs」にして追加します。

手順2 TitleAndPageクラス、TitleAndPagesクラスの定義

 先述したように、TitleAndPageはツールウィンドウの各情報を格納するためのクラスです。TitleAndPagesTitleAndPageのリストになります。

リスト2:TitleAndPage/TitleAndPagesクラス
public class TitleAndPage
{
    public TitleAndPage()
    {
    }

    public string Title { get; set; }
    public string PageUri { get; set; }
    public string IconUri { get; set; }
}

public class TitleAndPages : List<TitleAndPage>
{
    public TitleAndPages()
        : base()
    {
    }
}

手順3 SubWindowsにプロパティを追加する

 「SubWindows.cs」を開いてください。カスタムコントロールのC#コードは、このファイルに記述していきます。

 長いコメントの次の行にあるクラス定義を見てください。デフォルトではSubWindowsControlから派生しているはずです。このControlをContentControlに書き換えます。すると、このコントロールはContentプロパティを持つようになり、このコントロールの下の階層に置かれた要素は自動的にコンテンツとして扱われます。

 次にSubWindowsに3つのプロパティ、LeftContentsRightContentsBottomContentsを追加します。それぞれ、左右下のツールウィンドウのリストを格納することになるので、型はList<TitleAndPage>を継承しているTitleAndPagesになります。スタイル、バインディングなどのWPFの機能を利用できるようにするため、普通のCLRプロパティではなく、依存関係プロパティとして定義します。LeftContentsの定義は次のようになります。

リスト3:LeftContentsプロパティ
public static readonly DependencyProperty LeftContentsProperty =
    DependencyProperty.Register("LeftContents", typeof(TitleAndPages),
    typeof(SubWindows), new PropertyMetadata(new TitleAndPages() { }));
public TitleAndPages LeftContents
{
    get
    {
        return (TitleAndPages)GetValue(LeftContentsProperty);
    }
    set
    {
        SetValue(LeftContentsProperty, value);
    }
}

 依存関係プロパティは、通常DependencyPropertyクラスと“ラッパー”と呼ばれるプロパティを組にして使います。DependencyPropertyは依存関係プロパティの本体で、通常は静的で読み取り専用の公開フィールドとして定義します。

 登録時は、DependencyPropertyの静的メソッドであるRegisterメソッドを呼び出します。呼び出し時には、プロパティ名、プロパティの型、プロパティを定義するクラスの型を順に渡します。その後に続けて、プロパティのメタデータを渡すことも可能で、リスト3ではメタデータとしてプロパティの既定値(空のリスト)を渡しています()。

 ラッパーは、外部から依存関係プロパティを参照/設定する時に、通常のプロパティであるかのように扱えるようにするもので、getアクセサ内でGetValueメソッド、setアクセサ内でSetValueメソッドを呼び出します。

 RightContentsBottomContentsについては、LeftContentsとほぼ同様なので省略します。ダウンロードしたプロジェクトファイル内の「SubWindows.cs」を参照してください。

 なお、既定値を設定しないと実行時にプロパティの値がnullとなるため、NullReferenceExceptionが発生してしまいます。
 

手順4 コントロールの外観設定1 ~大きな構成要素を見る~

 使用するクラスとプロパティの定義が終わったので、いよいよコントロールの外観を設定していきます。しかし、XAMLコードで200行以上あって見難いため、まず大まかな全体像を説明した後、細かい部分を説明していきます。コントロールの外観設定は、「Themes」フォルダの「Generic.xaml」で行います。

リスト4:大まかな全体像
<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:WpfApplicationSubWindow1">
  <Style TargetType="{x:Type local:SubWindows}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:SubWindows}">
          <DockPanel>
            <ItemsControl Name="LeftTab" DockPanel.Dock="Left"
              ItemsSource="{TemplateBinding LeftContents}">
              ・・・
            </ItemsControl>
            <ItemsControl Name="RightTab" DockPanel.Dock="Right"
              ItemsSource="{TemplateBinding RightContents}">
              ・・・
            </ItemsControl>
            <ItemsControl Name="BottomTab" DockPanel.Dock="Bottom"
              ItemsSource="{TemplateBinding BottomContents}">
              ・・・
            </ItemsControl>
            <Grid Name="MainContent">
              <ContentPresenter/>
            </Grid>
          </DockPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

 コントロールの外観を最初から作成していく場合は、Templateプロパティに外観を書き加えていきます。

<Style TargetType="{x:Type local:SubWindows}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type local:SubWindows}">

 テンプレートには、コントロールの外観を作成するControlTemplateクラスと、データの表示方法を作成するDataTemplateクラスがありますが、この場合はコントロールの外観を作成するのでControlTemplateになります。

 ControlTemplate内はDockPanelによって左右下、そして中央の4つの部分に分割されています。

<DockPanel>
  <ItemsControl Name="LeftTab" DockPanel.Dock="Left"
    ItemsSource="{TemplateBinding LeftContents}">
    ・・・
  </ItemsControl>
  <ItemsControl Name="RightTab" DockPanel.Dock="Right"
    ItemsSource="{TemplateBinding RightContents}">
    ・・・
  </ItemsControl>
  <ItemsControl Name="BottomTab" DockPanel.Dock="Bottom"
    ItemsSource="{TemplateBinding BottomContents}">
    ・・・
  </ItemsControl>
  <Grid Name="MainContent">
    <ContentPresenter/>
  </Grid>

 そして、左右下の領域にはそれぞれItemsControlが、中央にはGridが配置されています。左右下のItemsControlには、それぞれLeftContentsRightContentsBottomContentsがバインドされ、中央のGridにはContentPresenterが配置されています。

 こうすることによって、左右下の領域にそれぞれのツールウィンドウ(とタブ)が、また、中央にコントロールのContentプロパティの内容が表示されることになります。

次のページ
手順5:コントロールのデザイン2 ~ItemsControlの表示設定~

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

Piz&Yumina(ピズアンドユミナ)

平成生まれの趣味プログラマー。開発&アニメ系ブログ「かおす★ぷろじぇくと」運営中。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2097 2008/08/26 13:11

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー