WPF超絶入門から学び直し2【XAML】

▼前回

https://qiita.com/YouKnow/items/6a0fefdfa5fdc4727d9f

***
:::note info
**今回のテーマ**
改めてXAMLって何者？
:::

※自分がC#erなのでC#を主語にして書いてるけどVBでも一緒。


# 【1】XAML理解のカギ
### :pushpin: HTMLみたいなやつ、と思ってたらむしろ混乱を招いた

**～不十分な理解～**
- XAMLはHTMLみたいなやつ
- HTMLと同じで見た目を書くやつ

これが別にあながち間違っているわけでもない。
小さくて簡単なアプリなら問題なかった。
しかしUIを作り込む案件で途端に混乱した…。

### :pushpin: XAMLの裏側にはクラスがいる

XAMLはマイクロソフト殿がXMLを拡張したマークアップ言語。
XAMLコードは、C#/VBなどの **.NET言語のクラス・プロパティと対応づけられる**。

- **WindowsフォームではUIをどうやって書くか**
    - **C#/VB**で書くよ
    - いろんなコントロールを表すクラスを使う
    - 階層構造が分かりにくかったりと可読性はよろしくない
    - でもフォームデザイナーに任せるからいいや
    - とはいえ外観をリッチにするとなれば手打ちが必要に → 可読性が悪い中で頑張る

- **WPFではUIをどうやって書くか**
    - **XAML**で書くよ
    - 化けの皮を剥がすと**C#/VBのコントロールを表すクラス**そのまんま
    - 見た目がマークアップ形式になったから階層構造が分かりやすい
    - いちおうXAMLデザイナーもあるから一定レベルまではお任せ可
    - 外観をリッチにしたくて手打ちする場合でも、可読性がマシだから柔軟性が上がる感じするね

つまり、
- インスタンスを生成する
- そのプロパティに値を設定する

などのザ・オブジェクト指向プログラミング！な処理を**マークアップ言語の見た目で書ける**のがXAML。

※XAMLはそもそも**UI特化言語ではない**とのことなので注意したい。

### :pushpin: XAMLはプログラミング言語だと思え

- XAMLはオブジェクトを組み立てるための言語。[(MS大田さん)](https://www.slideshare.net/okazuki0130/xaml-71503072)
- XAML というのは、要するに、XML のタグと .NET Framework のクラスを結びつける機構。[(++c++; // 未確認飛行C)](https://ufcpp.net/study/dotnet/wpf_xamlbasic.html#:~:text=%EF%BC%88XAML%20%E3%81%A8%E3%81%84%E3%81%86%E3%81%AE%E3%81%AF%E3%80%81%E8%A6%81%E3%81%99%E3%82%8B%E3%81%AB%E3%80%81XML%20%E3%81%AE%E3%82%BF%E3%82%B0%E3%81%A8.NET%20Framework%20%E3%81%AE%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%92%E7%B5%90%E3%81%B3%E3%81%A4%E3%81%91%E3%82%8B%E6%A9%9F%E6%A7%8B%E3%80%82%20%EF%BC%89%20%3CPage%3E,%E3%82%BF%E3%82%B0%E3%81%AB%E3%81%AF%20Page%20%E3%81%A8%E3%81%84%E3%81%86%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%8C%E3%80%81%20%3CWrapPanel%3E%20%E3%81%AB%E3%81%AF%20WrapPanel%20%E3%81%A8%E3%81%84%E3%81%86%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%8C%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

これらの端的な説明を目にし、すべてを悟ったのであった。

そして意識改革を実施した。
「XAMLはプログラミング言語」！！
いやマークアップ言語なんですけどね。
だけど、C#のつもりで、C#との対応づけを意識しながら読み書きしよう、という意識を持っただけでXAMLの理解が5倍速で進むようになった。

見た目はマークアップ、頭脳はプログラミング、迷言語XAML🎩👓🎀

# 【2】XAMLの構文
XAMLはXMLを拡張したものなので、XMLやその親戚であるHTMLが書けるなら何となくのフィーリングで書ける部分も多い。

だけどそれで勉強せずに分かっているつもりでいたら、そのうち詰まりだす。
その原因はXAML独特の構文。しかしやはりXAMLをC#に読みかえることさえ忘れなければスイスイ理解できる。

下2つはXAMLの基本構文を解説してくれている入門記事。どちらも似たような流れで体系的。

参考記事1：[WPFとXAMLの関係とは？ XAMLの基礎を学ぶ](https://atmarkit.itmedia.co.jp/ait/articles/1006/22/news101_3.html)
参考記事2：[XAML の基本構造（WPF）](https://ufcpp.net/study/dotnet/wpf_xamlbasic.html)

これ以降は自分のための備忘録としてこれらの記事のまとめ・補足メモをゆる〜く雑に残す。

### :pushpin: XAML超絶基本の構文

```xml:XML
<要素 属性1="値1" 属性2="値2" 属性3="値3">内容</要素>
<要素 属性1="値1" 属性2="値2" 属性3="値3"/>
```

```xml:XAML
<クラス プロパティ1="値1" プロパティ2="値2" プロパティ3="値3">コンテントプロパティ</クラス>
<クラス プロパティ1="値1" プロパティ2="値2" プロパティ3="値3"/>
```

- 要素名 → クラス名
- 属性名 → プロパティ名
- ""(ダブルクォート内) → プロパティの値
- 内容 → コンテントプロパティの値

- XMLでいう「空要素タグ」 → XAMLなどマイクロソフト用語では「自己終了タグ」。

- 1つの要素が1つのインスタンスになる。

### :pushpin: 開始タグと終了タグの間に書けるもの3種類

①コンテントプロパティ

```xml
<TextBox>こんにちは</TextBox>
```

②プロパティ要素

```xml
<TextBox>
    <TextBox.Text>こんにちは</TextBox.Text>
<TextBox>
```

③子要素(クラス要素)

```xml
<StackPanel>
    <TextBox></TextBox>
    <Button></Button>
</StackPanel>
```
※①～③を混在させたい場合は制約があるので参考記事を要確認。

### :pushpin: コンテントプロパティって何

XAMLで書けるクラスには、数あるプロパティの中でも特別な「**コンテントプロパティ**」が存在する。
- 通常のプロパティ・・・「属性」にプロパティ名を明記し、値を書く。
- コンテントプロパティ・・・「内容」にも書ける。プロパティ名の明記が不要。

(例) TextBoxのコンテントプロパティは Textプロパティなので…

```xml:
<TextBox Text="こんにちは"/> ←属性にも書けるし
<TextBox>こんにちは</TextBox> ←内容にも書ける
```

### :pushpin: コンテントプロパティの確認方法
- 公式Docでクラス定義を確認
    or
- VisualStudioでXAMLタグからクラス定義にジャンプ

→クラスについてる**ContentProperty属性**を確認。

```csharp:(例) TextBoxクラス
[System.Windows.Markup.ContentProperty("Text")]
// Textプロパティがコンテントプロパティに指定されている。
```

※もしContentProperty属性がついてなかったらベースクラスも遡って確認する。
(例) Buttonクラス → ButtonBaseクラス → ContentControlクラス

### :pushpin: 属性構文(Attribute Syntax)

プロパティをXMLの属性で指定する記法。
文字列で表せる(文字列に自動変換できる)型ならこの記法で問題なし。

```XML:属性構文(Attribute Syntax)
・構文
<要素 属性1="値1" 属性2="値2" 属性3="値3" />
```

- 文字列から自動変換できる型 
 string型, int型, bool型, DateTime型, Brush型 (色とか) 
など、そこそこ多くあるっぽい。

### :pushpin: プロパティ要素構文(Property Element Syntax)

XAML独特の記法。
プロパティを子要素のように入れ子構造で書く記法。
属性構文では書けない複雑な構造のオブジェクトにも対応できるのが特徴。

- **属性構文では書けない例**
    - 1つのプロパティに複数の値を持たせたいとき
    - プロパティの型が文字列に変換できない型のとき

```XML:プロパティ要素構文(Property Element Syntax)
・構文の例
<クラス>
    <クラス.プロパティ1>値1</クラス.プロパティ1>
    <クラス.プロパティ2>値2</クラス.プロパティ2>
    <クラス.プロパティ3>値3</クラス.プロパティ3>
</クラス>

・具体例
<TextBox>
    <TextBox.Width>80</TextBox.Width>
    <TextBox.FontSize>20</TextBox.FontSize>
    <TextBox.Text>こんにちは</TextBox.Text>
    <TextBox.Background>Pink<TextBox.Background>
<TextBox/>
```

### :pushpin: コレクションプロパティ

(例) StackPanelクラス
StackPanelのChildrenプロパティはUIElementCollection型。

```csharp:StackPanelクラス
public UIElementCollection Children { get; }
```

このChildrenのような**～Collection型のプロパティ**の中身(=要素)は、複数設定したければそのままズラズラと並列に書くことができる。
(～CollectionクラスはICollection, IEnumerable, IListの実装。)

```xml:コレクションプロパティの例
<StackPanel>
    <StackPanel.Children> ← ※コンテントプロパティなので省略可
        <TextBox/>
        <Button/>
    </StackPanel.Children> ← ※コンテントプロパティなので省略可
</StackPanel>
```

これをC#で書くと
```csharp:
StackPanel panel = new StackPanel();

TextBox textbox1 = new TextBox();
panel.Children.Add(textbox1);

Button button1 = new Button();
panel.Children.Add(button1);
```
階層構造が分かりにくくて嫌な感じ…。
こう見るとXML形式の記述のほうがUI作りに向いてるのを実感。

:::note info
**まとめ**
XAMLは、C#/VBなどの.NET言語がマークアップ言語の姿に変貌を遂げたやつ。
マークアップ形式だと、UIに関する記述がより分かりやすい。
:::

初期はXAMLデザイナーでドラッグ&ドロップして楽ちんだわ～とキャッキャ言っていたけど、ここまで知ると、外観を作りこむためにむしろ手打ちする前提だからこそXAMLを使っていることに気づいてしまったよねー。

HTMLみたいだからってなめてたら意外と勉強することあったし、まじでなめてた。

次回以降はもうちょっとｻﾞﾑﾙを掘って実践的な内容もしたいな〜
デザイン関係、いろんなバインド、依存関係プロパティなどなど‥‥。
けどもはや"超絶"入門ではなくなってしまうような‥‥‥。