I.はじめに
最近、Liu Tiemeng 氏の「WPF 徹底入門」を読んで、テンプレートの章の内容の一部について理解が深まったことがわかったので、記事を書きました。
記事のタイトルは「Control and Template」で、直訳すると「制御とテンプレート」になります。
この 2 つは理由もなく一緒にされるわけではなく、WPF ではこの 2 つは非常に密接な関係にあります。
2. コントロール
誰かがコントロールとは何かと尋ねたら、どう答えますか?
インターフェイス上のボタン、テキスト ボックス、スクロール バーはすべてコントロールです。
したがって、コントロールはインターフェイスのコンポーネントとして理解できます。
上記は私の以前の回答です。この回答に間違いはありません。非常に直感的です。厳密ではないかもしれませんが、多くの人が理解できます。
しかし、さらに尋ねると、
なぜ別の名前ではなくコントロールと呼ばれるのでしょうか? グラフィック要素と呼ばれる、インターフェイス上のこのインタラクティブなパターンは、より直感的で適切ではないでしょうか?
コントロールという名前は Control という単語から翻訳されたものであるため、コントロールと呼ばれていると答えるかもしれません。
他の人は、なぜ英語で Graphic Element ではなく Control と呼ばれるのかと尋ね続けるかもしれません。
このとき、なるほど、なぜ「コントロール」という言葉がついた名前なのか、と考え込んでしまいました。
この疑問を解消するにはどうすればよいでしょうか? 最も簡単な方法は Baidu です。
Baidu エントリ
コントロールとは、データとメソッドのカプセル化を指します。
コントロールは独自のプロパティとメソッドを持つことができます。プロパティはコントロール データへの単純な訪問者であり、メソッドはコントロールの単純で目に見える機能です。コントロールの作成プロセスには、設計、開発、デバッグ、およびコントロールの使用が含まれます。
百度の発言が正しいか間違っているかは別として、明らかに直感的ではありません。これをプログラマーではない人に説明しても、まだ理解できないかもしれません。
では、専門的な観点から見て、このコントロールの説明は意味があるのでしょうか?
プログラミングを学んだことのある人なら誰でも、プログラミングの本質はデータ構造とアルゴリズムであることを知っています。
インターフェイス上のコントロールは特定のコンテンツを表示し、いくつかの対話型メソッドを提供し、ユーザーは対話を通じてプログラムのステータスを変更できます。
では、コントロールによって表示されるコンテンツの本質は何でしょうか?
それはデータです。
コントロールによって提供されるインタラクションの性質/目的は何ですか?
例えばボタンを押すと、最終的にはプログラム内でメソッド(コード、つまりプログラムロジック)が実行され、その結果としてプログラムの状態が変化することがあります。
したがって、コントロールは、ユーザーが直感的にデータを確認できるようにデータを表現したものであるだけでなく、ユーザーがロジックを便利に操作できるようにアルゴリズムを表現したものでもあります。
各コントロールは「表現形式」として、ユーザーの操作アルゴリズムを実装し、特定のデータを視覚的に表示するために作成されます。コントロールの見た目は、その「アルゴリズムの内容」と「データの内容」によって決まります。内容が形式を決定するという哲学。
この観点から見ると、百度の声明は極めて合理的であり、規制の本質に近いものである。
3. テンプレート
次に、WPF のテンプレートに戻ります。
これまでの GUI テクノロジでは、コントロール内のロジックとデータは固定されており、プログラマが変更することはできませんでした (WinForms/Qt (QWidget) など)。コントロールの外観に関して、プログラマが変更できる変更は非常に限られていました。通常、コントロールのプロパティを設定するだけで、コントロールの内部構造を変更することはさらに不可能です。コントロールの機能を拡張したり、ビジネス ロジックに適した外観に変更したりする場合は、たとえわずかな変更であっても、多くの場合、コントロールをサブクラス化するか、UserControl を作成する必要があります。この状況の根本的な理由は、データとアルゴリズムの「形式」と「内容」が密接に結びつきすぎていることです。
WPF では、テンプレートの導入により、データとアルゴリズムの「内容」と「形式」が分離されます。
WPF のテンプレートは、次の 2 つのカテゴリに分類されます。
- ControlTemplate はアルゴリズム コンテンツの表現であり、ビジネス ロジックとの一貫性を高め、ユーザーがより快適に操作できるように、コントロールの内部構造をどのように編成するかを制御します。これにより、コントロールの「外観」が決定され、プログラマーはコントロールの元の内部ロジックに基づいて独自のロジックを拡張する機会が得られます。
- DataTemplate はデータ コンテンツの表現であり、単純なテキストであるか、直感的なグラフィック アニメーションであるかにかかわらず、データの表示方法を決定します。
一言で言えば、Template は「コート」です。ControlTemplate はコントロールのコート、DataTemplate はデータのコートです。
WPF のコントロールには固定イメージはなくなり、アルゴリズム コンテンツとデータ コンテンツの単なるキャリアになります。
コントロールは一連の操作ロジックが服を着ていると考えることができ、服を変えると別の外観に変化します。実際に表示されるコントロールのデフォルトの画像は、Microsoft が工場出荷時に着用するデフォルトの服です。
3.1 データテンプレート
実際のプロジェクトでは、ControlTemplate よりも DataTemplate の方がよく使われます。
名前が示すように、データのテンプレート/スキンです。オブジェクトを使用する場合、多くの場合、オブジェクトは外側のレイヤーにバインドされ、オブジェクトのプロパティは内部のさまざまなコントロールにバインドされます。
バインドされたコントロールを置き換えると、表示の外観も変わります。つまり、同じ内容を異なる形式で表示することができるソフトウェア設計を「データビュー」モードと呼びます。
WPF 開発では、DataTemplate は通常、次の 3 つの場所で使用されます。
- ContentControl の ContentTemplate プロパティは、ContentControl のコンテンツをドレスアップすることと同等です。
- ItemsControl の ItemTemplate プロパティは、ItemsControl のデータ項目をドレスアップすることと同等です。
- GridViewColumn の CellTemplate プロパティは、GridViewColumn セル内のデータを調整することと同等です。
3.2 コントロールテンプレート
前に述べたように、
表示されるコントロールのデフォルトの画像は、実際には Microsoft が工場出荷時に装着するデフォルトの服です。
ControlTemplate にはデフォルトの服装があり、ほとんどの場合デフォルトの服装で十分であるため、これを手動で変更する人はほとんどいません。
実際のプロジェクトでは、ControlTemplate を置き換える場合でも、成熟した UI ツールキットを使用してプロジェクトに導入し、そのスタイルを適用することがよくあります。
これは非常に合理的であり、前述したように、各コントロールは特定のユーザー操作アルゴリズムを実装し、特定のデータを視覚的に表示するように設計されています。これらの具体的な動作アルゴリズムはコントロールの性質によって決まりますが、明らかにデータよりも内容が固定されている部分ですので、Microsoft やプロのコンポーネント開発者に任せても問題ありません。
ただし、これは、一般のプログラマが ControlTemplate をまったく理解する必要がないという意味ではありません。場合によっては変更が必要になるためです。
『やさしくわかるWPF』という本にはこう書かれています。
実際のプロジェクトでは、ControlTemplate には主に 2 つの用途があります。
- ControlTemplate を置き換えてコントロールの外観を変更し、ユーザー エクスペリエンスと外観を向上させます。
- ControlTemplate を使用すると、プログラマーとデザイナーは並行して作業できます。プログラマーは、最初に WPF 標準コントロールを使用してプログラミングできます。デザイナーの作業が完了したら、新しい ControlTemplate をプログラムに適用するだけで済みます。
しかし、国内の WPF 開発の現状を考えると、デザイナーとプログラマーが完全に分業している人は少ないはずです。したがって、ControlTemplate の使用も最初の点に重点を置いています。
しかし、最初の点は前に述べたことと矛盾しているように思えます。ControlTemplate はレンダリング アルゴリズムではありませんか? コントロールの外観をどのように変更できるのでしょうか?
実際、コントロールの外観はコントロールの性質と密接に関係しているため、これは矛盾ではありません。
- ボタンの形状が似ているのはなぜですか? ボタンは通常、楕円形または長方形であり、クリック可能で、クリック後に沈み込みます。
- TextBox が常にテキストを入力できる長方形のボックスであるのはなぜですか。
- ScrollBar が常に長いバーなのはなぜですか? スクロールバーをドラッグして移動できます。
アルゴリズムとは何か覚えていますか?
どのプログラミング入門書にも、アルゴリズムが問題の解決策であると書かれています。
これらのコントロールがそのような外観と操作方法を備えている理由は、何もないところから作成されたものではなく、人間によって設計されたものです。明らかに、この設計はある種の問題を解決するためのもの、つまりアルゴリズムです。
コントロールの効果に満足できない場合は、実際のニーズに合わせて外観を変更する必要がある場合があります。
この時点で、ControlTemplate についてさらに理解が深まりました。コントロール テンプレートは、コントロールの外観と外部刺激に対する外観の応答 (ボタン マウス タッチ後のさまざまなイベント/背景色の変化など) を記述します。外観と刺激に対する応答のより深い意味は、これです。解決された問題の解決策を制御する必要があります。
以下は実際に開発中の ControlTemplate アプリケーションのシナリオですが、マウスがボタン上に移動したときにボタンの背景色が赤になるようにする必要があります (これは、マウスがボタンに移動したときにフィードバックを与えるためです)。
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="red">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
コードに示されているように、トリガーはマウスがコントロール上にあるかどうかをチェックするために使用され、そうであれば、主にコントロール テンプレートの外側の境界線の背景色を赤に変更することによって、コントロール テンプレートが変更されます。
3.3 コンテンツプレゼンター
実はButtonの構造はとてもシンプルで、
<Border>
<ContentPresenter/>
</Border>
境界線と ContentPresenter がボタンを形成します。
では、ContentPresenter とは何でしょうか?
逆コンパイルすると構造がわかります。私がコンパイルしたクラス図は次のとおりです。
ContentPresenter と ContentControl の構造がかなり重複していることがわかります。
私はここで些細なことを言うつもりはありませんし、彼らの関係を掘り下げることにあまり多くのスペースを費やしたくありません。
ContentPresenter は、コントロールのデータ コンテンツ テンプレート DataTemplate として直接理解できます。
一部のコントロールは ContentControl を継承しており、これをコンテンツ コントロールと呼びます。
TextBox など、それを継承しないコントロールもあります。
したがって、TextBox のデフォルトのコントロール テンプレートには ContentPresenter は存在しません。これもわかりやすいのですが、データの中身がないので、データの中身をどうやって表現するか。
Text 属性はデータ コンテンツではないのではないかと疑問に思われるかもしれません。
もちろんそうなのですが、コントロールの観点から見ると、Text のようなプロパティはすでに非常に基本的な、単なる文字列 (「アトミック データ」にやや似ています) であり、コンテンツ コントロールの Content は次のようにセグメント化する必要がある場合があります。ボタン。テキストの説明/アイコンなどが表示される場合があります。したがって、個人的には、Text 自体の単純な特性により、コンテンツ テンプレートとして表示されないようにすることを好みます。
4. 結論
主にコントロールと 2 つのテンプレートの理解について話して、たくさん書きました。
この理解は、WPF 開発 (WPF に限定されません) の内部の強みに似ており、コード作成の効率を直接向上させるわけではありませんが、長期的にはプラスの影響を及ぼします。