カスタムコントロールの作り方

せっかくなのでカスタムコントロールを作る方法を少しだけ.
画面は VS2010Pro のものですが,
上位の Visual Studio もほとんど同じでしょう.
Express の場合は多分メニューにカスタムコントロールライブラリが存在しない.

まず新しいプロジェクトを追加するダイアログで
「WPF カスタムコントロールライブラリ」を選択する.
001

既定のテンプレートで生成してくれるファイル群は
以下のようになっていると思います.
002

いくらなんでも “CustomControl1” なんていうコントロール名を作る人はいないと思うので,
こんなファイルは思い切って削除します.
続いて Generic.xaml を開いてみると,
先ほど削除してしまった CustomControl1 に関する Style が記述してあるので,
こちらも削除します.

これは削除後の Generic.xaml です.

ただの空っぽの ResourceDictionary です.

ようやくここからやりたいことをやります.
私の場合は LineGraph という名のコントロールを作成するので,
次のような構成になるようにファイル/フォルダを追加します.
003
LineGraph.cs はクラスとして追加し,/Graph/Themes/Generic.xaml はリソースディクショナリとして追加しています.
次に,一番最初に編集した /Themes/Generic.xaml を次のように編集します.

こうすることで追加した /Graph/Themes/Generic.xaml が自動的に読み込まれるようになります.
次に LineGraph.cs を次のように編集します.

名前空間は,このコントロールを実際に使う側のことを考慮して
シンプルに CustomControls のみとしています.
17 行目の処理が非常に重要なのですが,
ここではおまじない的に入れておきます.
続いて自分で追加したほうの Graph/Themes/Generic.xaml を次のように編集します.

“local” という名前で CustomControls 名前空間を定義し,
local:LineGraph の Style を定義します.
Style とはいっても,Template に対して ControlTemplate を指定しているので,
LineGraph コントロールの外観の定義そのものということになります.
ここでは試しに TextBlock をひとつだけ置いています.

さて,
カスタムコントロールライブラリのプロジェクトだけでは,
作成したコントロールの動作確認ができません.
試しにいつものように F5 とかで実行すると次のように怒られてしまいます.
007

というわけで,エラー内容にもあるように,
普通の WPF アプリケーションのプロジェクトを
同じソリューションに追加します.

ソリューションエクスプローラに表示されている
ソリューションの上で右クリックして,
「追加 → 新しいプロジェクト」を選択し,
「WPF アプリケーション」を追加します.

ソリューションエクスプローラに追加された
WPF アプリケーションのプロジェクトの上で右クリックして,
「スタートアッププロジェクトに設定」を選択します.
すると,WPF アプリケーションのプロジェクトのほうが太字で表示されるようになります.
004

この状態で F5 を押すなどして実行すると,
CustomControls プロジェクトもビルドされますが,
実際に実行されるのは SampleApp プロジェクトのほうとなるため,
MainWindow が表示されるようになります.

この状態が確認できたら,
SampleApp プロジェクトの「参照設定」を右クリックして「参照を追加」を選択し,
「プロジェクト」タブから CustomControls を選択して,
CustomControls プロジェクトを参照するように設定します.
下図は参照の追加をした後のソリューションエクスプローラです.
参照設定ツリーの下に CustomControls があるのがわかると思います.
005

ここまできたらあと一息です.
MainWindow.xaml を次のように編集します.

WPF デザイナが自動更新されて既に確認できているかもしれませんが,
念のため F5 を押して実行してみて下さい.
MainWindow に独自に設定した LineGraph コントロールが表示されていることが確認できます.
006

今後のデバッグはこのソリューションを使っておこなっていきます.
さらに別のカスタムコントロールを追加するときも,
このソリューションに追加することで簡単に対応できると思います.

以上.
思ったより長くなった….

LineGraph という名のカスタムコントロールを作ってみる その 1

WPF でグラフ表示をするためのコントロールを自作したい.
WPF Toolkit とか使えばいいじゃんとかいうツッコミもあるかもしれないが,
結局自分の思うようなカスタマイズをするにはやっぱり自作しかない.

とりあえず折れ線グラフをターゲットとして考えているので,
カスタムコントロール名も LineGraph としています.

というわけで今回は LineGraph コントロールの構成のお話.
中見はほとんど空っぽだけど XAML で書くとこんな感じに考えています.

まず,グラフタイトルと軸ラベルは単純に TextBlock を置いて,
依存関係プロパティを追加してバインドするようにします.

次に,軸目盛の数値は ItemsControl を利用して配置します.
ItemsSource には AxisItem という独自クラスのコレクションを指定しますが,
詳細はまた後日.

軸目盛のグリッド線も同じく ItemsControl で描画しようかとも思いましたが,
ここではひとつの Path オブジェクトで描画させます.
なのでグラフを表示する領域に Canvas を被せてそこに描画します.

データ点および点を結ぶ線については ItemsControl の中で記述できないかな~なんて考えています.

以上の構想を踏まえてグリッド線だけ描画させるとこんな感じ.
GridOnly

ちなみに MainWindow の XAML は下記のとおり.

LineGraph コントロールは Control から派生させて作成しています.
したがって,MainWindow.xaml の中の LineGraph コントロールに設定されているプロパティのうち,
BorderBrush/BorderThickness/Background 以外のプロパティは
すべて依存関係プロパティとして自分で追加したものになっています.

そろそろ長くなってきたので今回はこの辺で.
次回はグリッド線をどうやって描画しているのかを紹介しようかな.

ResourceDictionary を分割して使う

ResourceDictionary でリソースを書けるのはいいけど,
MainView では使わないけど Sub1View と Sub2View では使うものがあったりすると困る.
それにひとつの ResourceDictionary だとリソースが増えていくとやたら長くなって可読性も悪い.

というわけで ResourceDictionary を分割する方法です.
細かいネタだけど,カスタムコントロールを作るときの基本でもあるので
ここにメモしておく.

例えば色に関するリソースを Color.xaml として次のように定義する.

SolidColorBrush を 3 つ定義しているだけです.
このリソースを使いながら Border コントロールに関するリソースを Border.xaml として次のように定義する.

ここでもう出てきてしまいましたが,
ResourceDictionary.MergedDictionaries というのが今回のメインです.
Merged とあるように,複数の ResourceDictionary を結合するときに使います.

これらの ResourceDictionary を使用する MainWindowResource.xaml を次のように定義します.

このように,並べて書くだけで複数の ResourceDictionary を結合できます.
そんなわけで例えばこんな MainWindow.xaml を書きます.

実行結果.
ScreenShot1

Border の上にマウスカーソルを乗せると背景色が変化します.
Border.xaml で定義した動作が反映されています.
ScreenShot2

以上小ネタでした.

ItemsControl でデータ点を並べる

WPF でグラフ表示をしたいと常々思ってはいるんだけど,
VC++ のように自分で描画させるコードをしこしこ書くのはなんか違うと思い,
web 上で探しまくった結果,
結局のところ ItemsControl を使うんじゃないかと思い始めた今日この頃.

そんなわけで ItemsControl でデータ点を並べる XAML を書いてみた.

ItemsPanelTemplate でアイテムを並べるパネルに Grid を指定.
各アイテムは System.Point 構造体で,
これがそのまま描画する座標になっている.

ItemsPanelTemplate で Grid を指定できることは知っていたけど,
まさかこんな使い方をするなんて全然思いつきませんでした.
ItemsControl と DataTemplate の底力を垣間見た瞬間だった.
だいぶ頭固くなってきたな~.

というわけで実行すると次のように点が並びます.

ScreenShot

ItemsControl でグラフを表示するための入り口がなんとなく見えた気がするコードでした.

INotifyPropertyChanged を実装した抽象クラス

試しに INotifyPropertyChanged インターフェースと IDisposable インターフェースを実装した抽象クラスを書いてみる。

きれいに表示されているはず。

日々の開発日記など

書いてみようかと思い立ち、
WordPress までインストールしてブログを作ってみた。
開発は主に WPF + C# のデスクトップアプリケーション。
あんまり触ってる時間もないのでゆっくりまったりやっていきます。