XAMLをアプリケーション上で表示するXAML（XAMLを表示するXAMLを表示するXAMLを表示するXAMLもあるよ）

# まえがき
MaterialDesignInXamlToolkitのサンプルを久しぶりに見てみたら、大きく変わっていて、その中に面白い動きをする部分を見つけました。
それが今回紹介するXAMLを表示するXAMLこと`XamlDisplay`です。

# XAMLを表示するXAML
なにはともあれスクリーンショット

![スクリーンショット 2018-02-11 12.40.58.png](https://qiita-image-store.s3.amazonaws.com/0/120077/c43aabb5-e2ad-516c-30db-99392c0b63bf.png)

左側にXAMLの実行結果、右側にそのXAMLコードが表示されています。

上記画面のXAMLコードがこちらです。

```xml:MainWindow.xaml
<TextBlock Text="1- このTextBlockはXamlDisplayの外" />
<smtx:XamlDisplay Key="Unique1">
    <StackPanel >
        <Button Content="Some Content"/>
        <!--  コメントも表示される  -->
        <TextBlock Text="Some Text" />
    </StackPanel>
</smtx:XamlDisplay>
```

`XamlDisplay`で囲われた部分のXAMLコードが右側に表示されます。
もちろんButtonなどは正常に動作します。
またコメントも表示されます。

# 使用方法
まず最初にNugetから[ShowMeTheXAML.MSBuild ](https://www.nuget.org/packages/ShowMeTheXAML.MSBuild)を追加します。

次にApp.xaml.cs内にOnStartupのオーバーライドを追加します。

```csharp:App.xaml.cs（部分）
protected override void OnStartup(StartupEventArgs e)
{
    ShowMeTheXAML.XamlDisplay.Init();
    base.OnStartup(e);
}
```

次に表示したい部分を`XamlDisplay`で囲みます。
ここで面倒なことがあり、`Key`にアプリケーション内でユニークな文字列を指定する必要があります。
うーむなんとか自動化したい。

```xml
<smtx:XamlDisplay Key="UniqueKey">
    ...
</smtx:XamlDisplay>
```

これで囲われたXAMLが表示されます。

## デザイン調整
必須ではありませんが、XAMLコード表示部分のデザインを良くするために、外部ライブラリを使用します。
Nugetから[ShowMeTheXAML.AvalonEdit](https://www.nuget.org/packages/ShowMeTheXAML.AvalonEdit)を追加します。

注）記事作成時ではAvalonEditのリリース版にはバグが有り、表示が崩れています。
ですのでその修正を含んだプレスリリース版の1.0.10-ci44を使用しています。

App.Xamlにリソースを追加します。

```xml:App.xaml
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/ShowMeTheXAML.AvalonEdit;component/Themes/xamldisplayer.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
```

これでXAMLコードが色付けされて見やすくなりました。
内部的にはAvalonEditを使用しているようです。

![スクリーンショット 2018-02-11 12.56.48.png](https://qiita-image-store.s3.amazonaws.com/0/120077/4edfe851-7862-e2e9-c1b0-21c00780503a.png)

↓

![スクリーンショット 2018-02-11 12.57.14.png](https://qiita-image-store.s3.amazonaws.com/0/120077/4c921dae-a4c2-1795-465c-453eb4d5d5d8.png)



## 名前空間の削除
必須ではありませんが、標準ライブラリ以外を使用した部分を含めると、その名前空間も含めて表示されます。

このままですと、名前空間が長ったらしいので、それを非表示にします。
まず省略したい名前空間を含んだ`XamlFormatter`を定義します。

```xml
<smtx:XamlFormatter x:Key="xamlFormatter">
    <smtx:XamlFormatter.NamespacesToRemove>
        <system:String>clr-namespace:ShowMeTheXAML;assembly=ShowMeTheXAML</system:String>
        <system:String>clr-namespace:ShowMeTheXAMLTest</system:String>
        <system:String>clr-namespace:System;assembly=mscorlib</system:String>
    </smtx:XamlFormatter.NamespacesToRemove>
</smtx:XamlFormatter>
```

それを`XamlDisplay`の`Formatter`プロパティに追加します。

```xml
<smtx:XamlDisplay Key="Unique6" Formatter="{StaticResource xamlFormatter}">
...
</smtx:XamlDisplay>
```

これで名前空間が省略されて表示されます。

![スクリーンショット 2018-02-11 13.09.24 - コピー.png](https://qiita-image-store.s3.amazonaws.com/0/120077/72680ea4-f00d-bcfb-c37d-365025d23c2e.png)
↓
![スクリーンショット 2018-02-11 13.09.24.png](https://qiita-image-store.s3.amazonaws.com/0/120077/3e4a9146-5fe4-b651-fafc-b1dcdea29e7d.png)

# 使用例
## 文字のみ
文字のみ直接含めると、当たり前ですが左右でほとんど同じです。
![スクリーンショット 2018-02-11 13.33.14.png](https://qiita-image-store.s3.amazonaws.com/0/120077/10211197-f919-f7e5-b435-4a1fbe48d153.png)

```xml
<TextBlock Text="3- このTextBlockはXamlDisplayの外" />
<smtx:XamlDisplay Key="Unique3">
    AAAA
</smtx:XamlDisplay>
```

## もう少し複雑な場合
GridやMenuなど組み合わせて、少し複雑にした場合がこちらです。

![スクリーンショット 2018-02-12 12.31.14.png](https://qiita-image-store.s3.amazonaws.com/0/120077/59d4eaa1-014c-c3c3-3931-04cf161352c8.png)

```xml
<TextBlock Text="2- このTextBlockはXamlDisplayの外" />
<smtx:XamlDisplay Key="Unique2" Padding="5">
    <Grid Width="300">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Menu Grid.Row="0" Grid.ColumnSpan="2">
            <MenuItem Header="File" />
            <MenuItem Header="Edit" />
        </Menu>
        <CheckBox Grid.Row="1" Grid.Column="0"
            Content="Some Text1" />
        <Calendar Grid.Row="1" Grid.Column="1" />
        <Button Grid.Row="2" Grid.ColumnSpan="2"
            Content="BUTTON" />
    </Grid>
</smtx:XamlDisplay
```



## 動的な変更
表示されたXAMLコードはアプリケーション開始時の状態で固定されます。
ですので、ButtonClickイベントなどで要素を動的に変更しても追従はしません。

![スクリーンショット 2018-02-12 12.09.16.png](https://qiita-image-store.s3.amazonaws.com/0/120077/b3042935-0c00-831b-75e7-94093a3978e5.png)
↓
![スクリーンショット 2018-02-12 12.09.21.png](https://qiita-image-store.s3.amazonaws.com/0/120077/39c9e0d1-e788-45db-b116-6942f838e01b.png)

ButtonのクリックイベントでTextBlockの文字列を変更しています。
左側の文字列は"Some Text1"→"changed"に変わっていますが、右側のXAMLでは"Some Text1"のままです。


## XAMLを表示するXAMLを表示するXAMLを表示するXAML
ではこのXAMLを表示する`XamlDisplay`をさらに`XamlDisplay`で囲ったらどうなるでしょうか？
さらにはこのXamlを表示する`XamlDisplay`をさらに`XamlDisplay`で囲ってさらに`XamlDisplay`で囲うとどうなるか？。

こうなります。

![スクリーンショット 2018-02-11 13.38.01.png](https://qiita-image-store.s3.amazonaws.com/0/120077/a0995f58-25cf-fb39-8576-4685171cdced.png)

```xml:XAMLを表示するXAMLを表示するXAMLを表示するXAMLのコード
<TextBlock Text="4XAMLを表示するXAMLを表示するXAMLを表示するXAML- このTextBlockはXamlDisplayの外" />
<smtx:XamlDisplay Key="Unique4-1">
    <StackPanel>
        <TextBlock Text="4-1" />
        <smtx:XamlDisplay Key="Unique4-2">
            <StackPanel>
                <TextBlock Text="4-2" />
                <smtx:XamlDisplay Key="Unique4-3">
                    <StackPanel>
                        <TextBlock Text="4-3" />
                        <smtx:XamlDisplay Key="Unique4-4">
                            <TextBlock Text="4-4" />
                        </smtx:XamlDisplay>
                    </StackPanel>
                </smtx:XamlDisplay>
            </StackPanel>
        </smtx:XamlDisplay>
    </StackPanel>
</smtx:XamlDisplay>
```

## MaterialDesignInXamlToolkitのデモ
MaterialDesignInXamlToolkitではControlTemplateを使用して見た目を大きく変えています。

<⬣>ボタンをクリックすると、その左側の要素のXAMLコードがPopupで表示されます。
![スクリーンショット 2018-02-11 13.51.38.png](https://qiita-image-store.s3.amazonaws.com/0/120077/a2449adf-e497-53e7-0686-fbec246b2dfe.png)

見た目を大きく変えたい場合は、こちらを参考にすると良いと思います。

# 全体ソースコード
今回のサンプルコード全体をGithubにあげておきます。
https://github.com/soi013/ShowMeTheXAMLTest/tree/master

# 参考
[MaterialDesignInXamlToolkit-MainDemo.wpf](https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/tree/019c5d64836ca550f0ca780a4e33778f62be8bcb/MainDemo.Wpf)
[Keboo/ShowMeTheXAML](https://github.com/Keboo/ShowMeTheXAML)

# 環境
VisualStudio2017
.NET Framework 4.7
C#7.1
ShowMeTheXAML 1.0.10-ci44 
ShowMeTheXAML.AvalonEdit 1.0.10-ci44 
ShowMeTheXAML.MSBuild 1.0.10-ci44