WPF カスタムコントロール

Last Updated 2012/02/27


.Net Framework 3.5 の WPF 標準のコントロールはまだまだ多いとはいえません。.Net Framework 4.0 には DataGrid、DatePicker、Calendar の各コントロールが追加されましたが、それら以外にもほしいコントロールはたくさんあります。しかし、従来の .Net Framework 手法と比べると、WPF はカスタムコントロールを作ることが(圧倒的に)容易です。そこで、WPF 対応のコントロールを作ってみました。


XML 形式の初期化ファイル

アプリケーションはカスタマイズ情報などを保存しておくために初期化ファイルを使います。もっとも古いものでは INI ファイルでした。Windows 95 が出現したころからは Windows レジストリを利用する方法が一般的になりました。.Net Framework 時代になると、情報を XML 形式のドキュメントを使う方法が推奨されています。

.Net Framework にもアプリケーションの設定のための機能はあるのですが、ブラックボックスになる欠点があります。私自身は自分で管理したいと考えますので、XML 形式の初期化ファイルを操作するクラスを作ってみました。使い方は、INI ファイルと同じで、セクション名とキー名との組み合わせで項目を設定・取得します。

INI ファイルの内容は以下のようなものですが、これを XML 形式で実現しようとするものです。

[セクション名1]
キー名1=123
キー名2=abc
[セクション名2]
キー名3=123
キー名4=abc

また、オマケの機能として、フォームの位置とサイズを次回の起動時に再現する機能が付いています。続きは、「WPF グラフィックスオブジェクトのシリアル化」を参照してください。


カラー選択リストボックスコントロール

カラーを選択する機会は多いものですが、WPF には ColorDialog クラスがありません。そこで、リストボックスにカラーを選択する機能を付けてみました。戻り値は Color 型です。

コントロールは UserControl として作りました。下図は、コントロールをテストするアプリケーションを起動したところです。タブの左の [WEB] は 140 色の 標準 WEB カラーを色調別に整列したもので、[WEB(名前順)] は標準 WEB カラーを名前順に並べています。[システムカラー] はウインドウ各部位のシステムカラーです。

リストボックスから色を選択するとフォーム下部にある部分に選択した色とその色値を表示します。

ColorListBox

以下は、Visual Studio 2010 によるプロジェクトです。

ColorListBoxTest.zip (46,357 bytes)


カスタムコントロールのライブラリ化

ライブラリ化とは、DLL ファイル化です。WPF ではコントロールのカスタム化は XAML コードを使うことが多いので、直接 DLL ファイル化することはできません。もちろん、カスタムコントロールを XAML コードを使わずに、C# などの分離コードだけで作成することはできますが、ひどく面倒です。もともと、WPF では UI の設計には XAML コードを使うほうが便利にできているからなのでしょう。

さて、分離コードだけでカスタムコントロールを作成する場合は、従来の .Net Framework と同じ手順でライブラリ化が可能ですが、一部に XAML コードを使う場合の手順を説明します。「一部に」は正確な表現ではありませんが、要するに、XAML コードでコントロールのスタイルを定義する ResourceDictionary を作成し、分離コードでそのリソースを読み込んで、コントロールの Style プロパティに設定します。

以下のような XAML コードがあるとします。

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <Style x:Key="CircleButtonStyle" TargetType="{x:Type Button}">
    ....
    ....
  </Style>
</ResourceDictionary>

 XAML コードで定義した ResourceDictionary を分離コードを使って取り込むコードは以下のとおり。

namespace emanual.Wpf.Control
{
  [System.Drawing.ToolboxBitmap("Go3.bmp")]
  public class CircleButton : System.Windows.Controls.Button
  {
    static CircleButton()
    {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CircleButton), new FrameworkPropertyMetadata(typeof(CircleButton)));
    }

    public CircleButton()
    {
      this.InitializeControl();
    }

    private void InitializeControl()
    {
      ResourceDictionary dic = new ResourceDictionary();

      // 相対パスで指定しようとしたが、うまくいかなかった
      dic.Source = new Uri(@"D:\NET Framework\WPF\Control\CustomControl\CircleButton\CircleButton.xaml", UriKind.Absolute);

      this.Resources.MergedDictionaries.Add(dic);

      Style style = this.FindResource("CircleButtonStyle") as Style;

      if ((style != null) && (style != DependencyProperty.UnsetValue))
        this.Style = style;
    }
  } // end of CircleButton class
} // end of namespace

これでコンパイルすると、XAML コードを取り込んだ上で、DLL ファイルが作成されます。 


カスタムコントロールの登録

カスタムコントロールは、Visual Studio の IDE 内のツールボックスに登録しておくと、フォームのデザイン時に便利です。このための手続きは、従来の .Net Framework 環境と同じ手順で可能ですので、「コントロールのインストール」を参照してください。なお、ツールボックスに表示するビットマップの問題はいまだ解決していません。原因が同じではないのかもしれませんが、Button コントロールから派生したコントロールのビットマップは Button コントロールと同じビットマップになりました。

つまり、「カスタムコントロールのライブラリ化」で紹介したコードを見てもらえば分かりますが、ToolboxBitmap 属性でビットマップを指定しています。DLL ファイルにはビットマップのデータが含まれているのもかかわらず、ツールボックスにはそのビットマップを使いません。


−以上−