動機とか雑感とか
- WPF+C#(特にXAML)が使いこなせていないので「エッセンシャルWPF」を買ってみて読んでみる。
- 結構翻訳が微妙…というか無理…内容を理解して翻訳していないだろう…読み終わったら速攻でメル○リかも。
- 写経もいいのだが分量が多いのでしんどいので、あるリポジトリにおいてあったコードを勉強に使わせてもらった。ありがとうございます!
- この本を1冊目に読むのはキツい。C#を知らない人は無論無理。WPFを全く使ったことがない人にはほとんど参考にならない。
- WPFのWPFの本は本当に少ないがKindle Unlimitedに初心者向けのものもあるからチェックしてほしい。
- WPFの開発苦労話みたいなものも含まれている。興味がない人からするとノイズかもしれない。
1章 はじめに
- Windows FormsとWPFはUIの作り方が違うだけで根本的には同じなのかと思ったが、全然違うらしい。
- Windows Formsはラスタベース、WPFはベクタベースらしい。つまりWPFは拡大しても図などがザラザラしない。
- ほかにも表示系がいろいろ違うらしい。例えばボタンに画像と文字を一緒に表示するのも得意らしい(MFCでもできた気がするが…)
- XAMLをボタンの描画なども含めてIEできれいに表示できるみたいな記述があって「うそだあ」と思ってやってみたができなかった。
- XAMLのタグとC#の型には対応関係がある。どちらを使っても同じものが書けるようである(C#というよりCLRで走る言語かな)。
- XAMLでタグを追加するということは、C#でオブジェクトを作るのと等しい。逆もまた然りということか。
- XAML特有の謎なプロパティの書き方
x:Name
はC#における属性[STAThread]
とかとほぼ同様に機能するらしい。いわれてみればそんな気がしないでもない。ちなみにこのプロパティの書き方はマークアップ拡張と呼ばれる。
-
xmlns:x
とかxmlns:d
は使用する名前空間の指定をしている。ここでいえばx
やd
は名前空間名であり、XAML内の識別子として使用できる。だからx
ではなくxaml
だってよい。この名前空間の指定方法は2つあるようだ。- URLっぽく記述する(例:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
) - 読み込むアセンブリ(DLL)とアセンブリ内の名前空間を記述する(例:
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
)
- URLっぽく記述する(例:
- ウィンドウは1つのクラスであらわされるが、そのクラスは2つに分割される。1つ目はXAMLで記述し、コンパイルでC#に変換されるもの。もう1つは最初からC#で書くやつ(コードビハインドとも呼ばれる)。これらは
Partial Class
という仕組みで関係を持たせながらも独立して開発できるようになっている。 - Windows Formsと違うポイントとしてXAMLで使用するコントロールには必ずしも名前を付けなくてよい。名前を付ける場合は
x:Name
属性を使用する。 - あらゆるコントロールには
Resource
という属性があり、そこにはKey-Valueの形で属性値を書いておける。この属性値はそのコントロールに内包される子コントロールから参照することができる。 - 最後にコントロールの
Template
プロパティという非常に重要な機能についての言及があるが、何を言っているのかよくわからん。- どう考えてもこちらのページの説明がわかりやすい。
-
コントロールの形状などをむちゃくちゃカスタマイズしたい場合に
Template
というプロパティに形状情報などを記述するとよいということだ。
2章 アプリケーション
-
xmlns
とxmlns:x
は何が違うのか。これらはプロジェクト作成時に自動生成されるが、それぞれ微妙に違うURLが設定されて何がしたいのかよくわからん- こちらの神ページに説明が書いてある。
-
xmlns
は極めて基本的なベースとなるXAMLの機能を使えるようにするおまじない -
xmlns:x
は名前空間x
に割り当てる機能を指定する。x
はデータバインディングなどに使用するもので、xmlns
で指定したものよりもより高度な機能をアドインするようなイメージだろうか。
- 1章でも登場したがXAMLはWebアプリケーションの開発にも使えるらしい。Webアプリケーションの形式でビルドすると
.xbap
という拡張子が与えられたファイルとなり、ブラウザ上で実行できる。- これは知らなかった。でもオワコンらしい。
- WPFではMDI(Multiple Document Interface)をサポートしない。MDIは昔はよく見た気がするが、最近は確かにあまり見ない。
- そういえば、ウェブブラウザなんて1つのプロセスで複数のウェブサイトを閲覧できるが、これはMDIには含まれないのか。
- 例外に関して気になる記述があった。
回復が不可能な例外が存在するということです。典型的な例として、StackOverflowException、OutOfMemoryException、ThreadAbortExceptionがあります
- ふうん。どれも普段見かけない例外なのでよく知らんが、回復が不能な例外というのはCatchできないということか?
- たしかにStackOverflowExceptionのMicrosoft Docsには
Starting with the .NET Framework 2.0, you can't catch a StackOverflowException object with a try/catch block, and the corresponding process is terminated by default
という記述がある。 - 一方でThreadAbortExceptionのMicrosoft Docsには
ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block
と書いてある。Catchはできるけど握りつぶすことはできないという感じか。 - OutOfMemoryExceptionのMicrosoft Docsには特に記述はなさそうだった。試しにこの例外をわざとthrowしても普通にCatchできた。
- この
回復が不可能
っていうのはどういう意味なのか結局よくわからなかった。これらの3つの例外に処理上の共通点があるというわけじゃなくて、単に発生した場合はもう実行継続しないほうがいいよってことだろうか。
- Windowsデスクトップアプリに限らず、ユーザの設定情報を保存しておきたいことは多いだろう
- 本書では
ApplicationSettingsBase
というクラスを使用した設定の保存方法を紹介している。これは知らなかった。この神サイトではVisual Studioを使わない方法として紹介されている。なるほど。Visual StudioのGUI上で設定を作っていくのではなく、コード上でやりたい場合にとる手法なのか。 - ただ、特別な理由がなければこの神サイトのVisual Studioを使う方法のほうがわかりやすいような気がする。
- ほかにもXMLファイルやレジストリなどに出力する方法があるが、ファイルの管理を手動でゴリゴリやり始めると間違えて大事な設定を上書きしちゃったり、互換性が確保されなかったりといろいろ面倒なことも多い気がする。
- 本書では
- 子ウィンドウを親ウィンドウの上にフローティングさせながらも、親ウィンドウを選択可能な状態にするにはOwner属性を設定する。
- 恥ずかしながら知らなかった。このサイトにあるような効果もあるらしい。親を閉じたら子も閉じるようにするためにわざわざ通知を送ったりしていた過去があるなんて人に言えない…
- WPFでは画面遷移(Navigation)の機能が備えられている。要はWebページみたいにハイパーリンクで他のページに移動したり、戻ったりするというようなものだ。
- 登場人物は3名。
ナビゲーションホスト
、ページ
、ジャーナル
である。 - ナビゲーションホストはブラウザのようなものでページを表示させる土台となるものである。
- ページはブラウザに表示されるWebページのようなもので、実際のコンテンツの中身や他のページへのリンクが含まれる。
- ジャーナルは遷移の履歴情報である。ブラウザで戻る/進むの操作をしたかったら、どういう経路で遷移しているのかを覚えておく必要がある。それがジャーナルである。履歴といったもWebページの閲覧履歴とは違って、何か一本の動線のようなイメージだ。
- 登場人物は3名。
3章 コントロール
- WPFのコントロールの特徴はリッチなコントロールとシンプルなプログラミング性を両立したところといえるようだ。
-
リッチ
とはボタンの中にさらにボタンを含むような自由度や、様々なフォントや文字色、図形を組み合わせたゴージャスな表現力のこと。 -
シンプルなプログラミング
とはなるべく少ないコードで直感的にコントロールを表現できること。
-
- これを実現するのにWPFでは
コンテンツモデル
という仕組みを採用している。そのためのクラスがContentPresenter
である。-
ContentPresenter
はアダプターみたいなものだ。コントロールの上にContentPresenter
というなんでも固定できるアダプターを取り付けることでその上に文字を置くのもよし、画像を置くのもよし、複数の要素を置くのもよしというような感じに上に載るものを抽象化できる装置であると読めた。 -
ContentPresenter
のことを本書では"馬車馬"と表現しているが、それだとめっちゃ酷使されそうだが誤訳か?荷馬車?
-
-
ContentPresenter
はボタンなどの中身が1つのものに使用し、リストなどの複数の項目を一覧表示するにはItemsPresenter
を使用する。- ボタンの中に複数のコントロールを表示することは可能だが、あくまで表示する"キャンバス"は1つである。一方、ListBoxなどは"キャンバス"が明確に区切られている。よって
ItemsPresenter
を使用することになる。 -
ListBox
はListBoxItem
という子要素の集まりである。ListBoxItem
はボタンと同様にコントロールを表示する"キャンバス"は1つだけだからContentPresenter
を使用する。よってListBox
の下にItemsPresenter
があり、その中には複数のListBoxItem
が含まれていて、それぞれにContentPresenter
があるというような構造か。
- ボタンの中に複数のコントロールを表示することは可能だが、あくまで表示する"キャンバス"は1つである。一方、ListBoxなどは"キャンバス"が明確に区切られている。よって
- コントロールの種類は
コンテンツコントロール
、レイアウトコントロール
、レンダコントロール
の3つ。- コンテンツコントロールはボタンやリストなどのこと。
- レイアウトコントロールは
StackPanel
などの他のコントロールを制御するもの。 - レンダコントロールは画面上にピクセルを表示するものである。例えば画像とか矩形とか。
- ここまではコントロールの中に何を描くかだったが、次はコントロールの見た目の話だ。当然、何を書くかは見た目の一部であるから、より上位の概念を考えることになる。
- コントロールの見た目はコントロールのプロパティ
ControlTemplate
で設定する。ControlTemplate
の中にボタンの外形や枠などの見た目の情報や、前述のContentPresenter
などを階層構造に記述していく。これをVisualTree
と呼ぶことがある(?)ようだ。 -
ControlTemplate
についてはこれやこれなどの文献のほうがわかりやすい。 - 知らなかったがXAMLではなく、コードでControlTemplateを記述する方法もあるようだ。まあわからんでもない内容だがXAMLのほうが階層がはっきりしていて好み。
-
ControlTemplate
を使うと名前の通りテンプレ化することができる。つまりボタンの見た目を簡単に統一することができる。そういった点でいうと、このページに書いてあるようにリソースにControlTemplate
を書く方法が最高にクールだと思う。
- コントロールの見た目はコントロールのプロパティ
-
ItemsControl
はリストのように複数の項目からなるリストである。ここの最高に明快な解説のとおり、普通にリストのソースにコレクションを指定するだけでは全然使い物にならないリストである。様々な属性を設定しながらリストをリッチにしていく必要がある。- 上で紹介した記事と同じ作者だとおもうけど「WPF実践」の6章の説明がわかりやすい。
- なんちゃらTemplateが一体どこに効いてくるのか、どんな書き方をすればいいのかは難しい。上記の「WPF実践」もわかりやすいが、こちらの記事もあわせて読んで実際に何かコントロールを作ってみるとわかりやすい。
- 訳者の人には悪いが全体的にヒドい訳だ。英単語をそのまま翻訳して、英語の語順を日本語のものに直しただけというような印象すら受ける。本当に内容を理解して訳したのか疑問だ。
- WPFにはほかにも様々なコントロールがある。
InkCanvas
なんてめちゃくちゃ面白そうだが、一生使うことはないんだろうなあ。
4章 レイアウト
- レイアウトとは3章で出てきたようなコントロールをどのように配置するかということである。
- WPFのコントロールの特徴は
ContentPresenter
を使用してコントロールの中にコントロールを入れるネストができることであった。レイアウトもそれと同様にレイアウトの中に他のレイアウトをネストすることができる。 - レイアウトのネストができるようになると親レイアウトと子レイアウトというような親子関係が生まれる。ここで問題になるのがその親子間でのデータの受け渡しである。その受け渡しの技術をコントラクトというらしい。
- WPFのコントロールの特徴は
- コントロールの位置調整の方法として
RenderTransform
とLayoutTransform
の2つのプロパティがある。-
RenderTransform
はレイアウトの決定後に位置調整する。たとえばボタンを整列するようにレイアウトしていて、そのなかのボタンをRenderTransform
で位置変更したら、他のボタンの位置を乱すことなくボタンの位置が変わる。 -
LayoutTransform
はレイアウトの決定時に位置の調整分を加味する。 - このサイトの図を見てもらえばわかりやすい。Button Twoと書かれたボタンが位置調整されているが、レイアウトが決まってから回転しているのか、レイアウトを決めるときに回転が加味されているのかがわかりやすい。
- どちらがよいのかという話だが、
RenderTransform
のほうがレイアウトの再計算が必要なく、ビデオカードで位置調整が可能だからパフォーマンスとしては優れているようだ。
-
- コントロールを並べてレイアウトを制御するための土台(いわば台紙)をパネルと呼び、
Canvas
、StackPanel
、DockPanel
などがある。- パネルを使用するうえで興味深いのが添付プロパティである。
<Canvas...><Button Canvas.Top=".../></Canvas>
のように本来Button
が知りえない(Buttonクラスのプロパティに含まれるはずのない)Canvas.Top
というプロパティを、あたかも持っているかのようにButton
がふるまっている。これはいまだにどういう仕組みなのかよく理解できていないが、ここの説明が簡潔で分かりやすい。 -
Canvas
はいわばウィンドウという掲示板に張り付けられた紙
である。この紙の中に表示されるコントロールは紙の左上の位置からの相対位置で配置することができる。よって紙の場所を変更したらコントロールも紙との位置を維持したまま移動するというわけだ。 -
StackPanel
は特定の方向にコントロールを並べていくだけ。 -
DockPanel
は特定の方向にドッキングするパネル。特筆すべきことはないが、DockPanel
の中に入れた最後の要素が残りの領域を占有するという特徴がある。つまりXAMLの記述順序がレイアウトに影響するというわけだ。わかりやすい文献が山ほどある。 -
WrapPanel
は折り返し可能なStackPanel
のようなものだ。ある方向にコントロールを並べていくが、領域内に収まりきらない場合は次の行や列に折り返して表示される。 -
UniformGrid
は超単純なグリッド(格子状)レイアウトだ。行数と列数を決めるとコントロールを同じ大きさのセルに順番に並べてくれるだけ。機能が少ない分シンプルだから結構使いどころありそうだな。 -
Grid
はUniformGrid
の上位版である。UniformGrid
ではできなかったセルの大きさを細かく調整することやセルを結合することが可能になる。Grid
の最大の特徴は他のパネルと違ってXAMLの記述順序とレイアウトが分離できる点だ。他のパネルは書いた順に並べられていくが、Grid
は順序をプロパティで指定する。よってレイアウトの変更も簡単に行うことができる。
- パネルを使用するうえで興味深いのが添付プロパティである。
-
Grid
のセルの幅はピクセル単位、割合(例: 2*)、内部のコントロールに合わせる(Auto)の3パターンで指定できる。 -
Grid
のセルの大きさはSharedSizeGroup
というプロパティを使って他のセルやGrid
と共有することができる。 - これらの標準的なパネルでは表現できない凝ったレイアウト(例えばコントロールを円形に並べたいとか)にしたい場合はカスタムレイアウトを作る必要がある。
- 本書ではページ数はそれなりに割かれているものの断片的にしか書かれていない。ほとんど使うことなさそうだけどな。
- カスタムレイアウトについては日本語の文献が少ないが、この英語の文献をまず読むとやるべきことがはっきりする。なるほど
Panel
から派生させて実現したいレイアウトになるようにメソッドをオーバーライドするのね。
5章 視覚要素
- あんまり使わないので詳細は覚えようとせずに「そんなもんがあったな~」と後から思い出せる程度に読んでおく。
- 2Dグラフィックスの要素は
ジオメトリ
、ブラシ
、ペン
の3つに集約される。これらを組み合わせて2Dのグラフィクスをデザインしていく。- ジオメトリは形状のことであり、矩形や円、直線、自由曲線(パス)が含まれる。あくまで形状であって色はブラシなどで決まる。
- ブラシは塗りつぶしのことである。
- ペンは形状の外形線のことである。
- WPFの設計原則に解像度非依存がある。ディスプレイの解像度によらずアプリケーションは同じ見た目に見えるべきだということだろう。
- よくWPFは高DPI対応しているというのがメリットだといわれる。高DPIの問題がどのようなものかについてはこの資料をみるとよい。最近はWinFormsも高DPIに対応しているみたいだからこの点ではWPFの優位性はないみたい。
- WPFは1/96インチという論理ピクセルを用いて座標を表現しているらしい。つまり、実際のディスプレイのピクセル数を意識することなく開発ができるということのようだ。
- WPFで扱える色の記述方法には
sRGB
、scRGB
、Adobe 1998カラープロファイル
などが使えるようだ。- よく使う"いわゆるRGB"は
sRGB
のようだ。それぞれの記述方法で色を表現できる範囲(細かさではなく、色を表現できる幅という感じか)が違うようだ。
- よく使う"いわゆるRGB"は
- ペンはジオメトリの輪郭を描くために使用する。ジオメトリはいわば頂点の集まりであって太さや色を持っていない。ペンを使ってその外形線を書いてあげる必要がある。
- 線の端点の形状などInkscapeみたいな感じの柔軟な指定がいろいろできる。
- WPFはもちろん画像も扱うことができる。正直画像を扱うクラスはいっぱいあってよく違いがわからないが、必要になったらまた調べればいい。
- アニメーションを使うことで動的なUIを実現できる。自前でタイマーを作り、定期的にアニメーション化したい物体のプロパティを変更するというような不細工なことをしなくてもWPFにはいろいろな便利な機能がある。
6章 データ
- WPFといえばデータバインディングである。これは見た目(ビュー)とロジック(モデル)を分離するための手法である。
- アプリケーションの見た目はデザイナーにやってもらいたいが、内部のロジック・処理は専門的なエンジニアにやってもらいたいというような場合にお互いの作業領域があまりに干渉しすぎるとどちらか一方がボトルネックになったりして作業がしにくいことが考えられる。
- ビューからロジックを分離すると再利用性が向上する。ロジックの中にこのボタンの見た目を…みたいな処理を書いていたら、そのロジックをほかの機能で使いたいと思ってもボタンの処理が邪魔で再利用することができない。
- 最近流行しているアジャイル開発ではテストの自動化が重要なキーワードである。しかし、ロジックがビューに依存しているとロジックをテストしようと思ってもビューとの協調や人間の操作が必要になる場合があり、自動化が難しくなってしまう。
- まずはリソースの話。WPFは1つのコントロール(要素)は1つしか存在できないという原則があるようだ。そりゃあ確かにそうだ。ボタンを1つしか定義していないのにそれを複数の場所に同時に配置しようなんてことができないのは容易に想定できる。だから、以下のコードはうまくいかない。2つめの
Button
にしかTextBox
が表示されなかった。
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<TextBox x:Key="sharedTextBox">おれはここだああ</TextBox>
</Window.Resources>
<StackPanel>
<Button Content="{StaticResource sharedTextBox}"/>
<Button Content="{StaticResource sharedTextBox}"/>
</StackPanel>
</Window>
-
StaticResource
はリソースのオブジェクトをコピーしてリソースの設定をするが、DynamicResource
はリソースのオブジェクトの参照を渡すようだ(そう読めた。違っていたらすみません)- 例えばリソースに定義された
Button
のBackground
にStaticResource
でSolidColorBlush
を参照した場合、後からリソースの値を変更してもButton
のBackground
は変わらない。一方でDynamicResource
にすると後から変更することができる。つまり、リソースの状態が常に監視された状態になるということだ。
- 例えばリソースに定義された
- 私の知るデータバインディングとはリソースの話ではなく、XAMLとC#のコードを橋渡ししてデータのありかを指定する方法のことである。このデータバインディングは
ソース
とパス
を指定する。要はどのオブジェクトの(=ソース)のどのプロパティ(=パス)を紐づける(バインディング)のかを設定する。-
textBox1
という名前のオブジェクトのText
プロパティを参照するなら{Binding ElementName=textBox1, Path=Text}
と書く。 - データバインディングは何かというのを一言で説明するのは非常に難しいので先人の素晴らしい記事を参照してほしい。
-
- データバインディングはあるプロパティに変数を代入するようなものであるが、ここでひとつ問題が発生する。
- 代入するとなるとどうしても型を意識しなければならない。例えば
string
型のプロパティにint
の型の値を代入することは一般にはできない。 - データバインディングも同様で、バインディングされる側とする側の型を意識しなければならないが、これを上手に変換してくれる強力な機能として
コンバータ
がある。このあたりの記事の説明がわかりやすい。
- 代入するとなるとどうしても型を意識しなければならない。例えば
- データバインディングで重要となるのはデータの同期である。
- データバインディングはC#でデータソースを指定して、XAMLで表示するわけだが、どちらかの値が変更されたらもう一方にうまいこと通知してあげないと不一致が生じてしまうし、都度代入する処理みたいなものを自前で書いていたら非常に面倒である、
- 動機をする方法として本書では3つ挙げている。(1)
INotifyPropertyChanged
を実装する (2) 変更をプロパティに報告するイベントを作成する (3)DependencyProperty
ベースのプロパティを作成する - 恥ずかしながら**(2)は何のことかわからなかった**。Windows Formsなどでサポートされていると書かれているので、このあたりの記事で述べられている方法なのかもしれない。
- View(XAMLで書くやつ)とModel(データそのもの)を結びつけるのがデータバインディングだが、Model側の変更がViewに反映されるためにはModel側から通知をしてあげる必要がある。それをするのが
INotifyPropertyChanged
である。- WPFの極めて重要な仕組みであるにも関わらず、実現するために書かないといけないコードが妙に多い。このあたりの記事を見ると解決方法がわかる。
- XAMLはXMLをベースに作られているからXAML内にXMLのデータ構造やXPathのクエリが使用できる。このあたりの記事に使い方が書いてあるが、でもこれってどういうときに使うんだろう。
-
ItemTemplate
(リスト系のコントロールの各要素の表示を決める属性)はDataTemplate
オブジェクトで指定するが、複数のDataTemplate
の中からどれを使用するかを条件に応じて変更したい場合がある。これにはItemTemplateSelector
を使用する。 - リスト系のコントロールには
IsSynchronizedWithCurrentItem
という属性があり、これをTrue
にすると複数のコントロール間の値をデータバインディングによって同期することができるらしい。いろいろ使えそうだよね。 - コレクションをソートしたりグループ化して表示したい場合は
CollectionView
を使用する。- あくまで表示時にソートなどの処理を行うのであって、コレクションそのものがソートされている必要はない。要はView側で簡単なデータ処理をやってしまうというわけだ。
- 単一のコレクションから複数のViewを作れるちゃうから、Viewのためにわざわざモデル側を変更しなくてよくなる。詳しくはこのあたりを見るとよい。
7章 アクション
- データバインディングは見た目とロジックを連携させる仕組みであった。一方でアクションはユーザの操作などの入力に対してロジックがどのように反応するかに関するものである。
- まずはシンプルなイベントハンドリングの話。
Button
のClick
イベントとかである。- ボタンを押すという点では
Click
やMouseDown
のイベントがある。同じように使えるのかというとそうではない。 -
Click
はより抽象的な概念であって、マウスクリックはもちろん、ボタンをフォーカスした状態でSpaceキーを押したような場合も含まれる。操作そのものを表しているのではなく意味を表しているといえるだろう。 - 一方
MouseDown
は露骨に操作だ。マウスクリックという操作が行われた場合のイベントだ。 - WPFはこのような様々なレベルの抽象度(本文中では結合と呼んでいる)のイベントを扱うことができるようにしている。
- ボタンを押すという点では
- WPFはUIの自由度がやたらと高く、ボタンの中にボタンを作ったりすることができる。したがって、これまでのWindowsアプリケーションで使用されるようなイベント(CLRイベントというらしい)では対処しきれない。そこで、WPFではルーティングという仕組みが用意されていてイベントを自由自在に操れるようになっている。
- イベントは3種類ある。
直接イベント
とバブルイベント
とトンネルイベント
である。詳細はここを見てほしい。-
直接イベント
はCLRイベントとほとんど同じらしい。イベントが発生したらその発生源のイベントハンドラのみ実行される。 -
バブルイベント
は発生源の要素から出発して、上位の要素に向かって広がっていくようにハンドラが実行されていく。例えばWindow
の中にGroupBox
があり、その中にButton
があったとしてButton
をクリックしたらButton
→GroupBox
→Window
の順にイベントハンドラが連鎖的に呼び出される。 -
トンネルイベント
は最上位の要素から発生源の要素に向かって穴を掘り起こしていくようにハンドラが実行されていく。上の例でいえばWindow
→GroupBox
→Button
の順にイベントハンドラが連鎖的に呼び出される。
-
-
トンネルイベント
はかなり特殊な感じがする。なんてったって一番最初に発火するのが一番遠いところだからだ。トンネルイベント
は接頭辞にPreview
がついていて、ボタンがクリックされたことを上位の要素で打ち消したいときなどに使用する。 - 次に
コマンド
である。WPFの代表的な機能であるデータバインディングからわかるように、WPFでは見た目とロジックをなるべく分離する。XAMLを見た目を作るUI要素を定義できるだけでなく、UI要素を操作したときにどういったイベントを発生させるかも定義できる。 -
トリガ
はプロパティの値の変化が発生したときにUIの見た目を変更する機能である(おそらく見た目だけじゃないのだろうけど)。- マウスオーバーでボタンの色を変えたり、数値の入力値に応じて画面表示を変更したりすることができる。
8章 スタイル
- WPFはかなりWebに影響を受けている。HTMLとCSSの関係のように画面の構成要素とそのスタイルを分離することができる。
- スタイルの適用には優先順位がある。このMicrosoft Docsやこの記事でも述べられている。実際にサンプルを動かしてみたほうが早い。
- 過去のWindowsのUI風のテーマやサードパーティの
テーマ
を適用することができる。さらにテーマをベースとして色合いなどをユーザがカスタマイズ可能にするスキン
の仕組みも実現することができる。 - アプリケーションの外観は一貫性が最も重要である。同じアプリケーション内で見た目がコロコロ変わる(本書ではこれをフランケンシュタインアプリケーションと表現している)
- 見た目にこだわるなら全部のコントロールについて見た目をこだわるべきだ。ボタンはめちゃくちゃリッチな感じの見た目だけど、スライドバーは標準的なダサいやつだとダメである。
付録
- スレッドやユーザの入力に関することが述べられているが、とりあえず読まなくていいだろう…