[UWP]同じようなXAMLを書きたくない。テンプレートコントロールを使う

UWPの基本パーツは、プリミティブなものばかりで、それらを組み合わせていかないといけない。
一回だけならまだしも、何回も繰り返すと、流石に嫌になる。

```xml:
 <Grid>
      <Grid.RowDefinitions>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition></RowDefinition>
       </Grid.RowDefinitions>
       <TextBlock Text="Header"></TextBlock>
       <TextBlock Grid.Row="1" Text="Content"></TextBlock>
  </Grid>

```

上の例では、ContentにHeaderを付けたいだけだが、XAMLとしては、６行を消費している。レイアウト情報が多いため、記述は冗長であり、意味的なものを把握しにくいものになっている。何度も書くものではない。

このようなときには、「テンプレートコントロール」を使う。

「テンプレートコントロール」は、csファイルと　Generic.xamlにテンプレートが追加される。このふたつがペアで機能する。


```csharp:HeaderControl.cs

namespace MyUwpLib.Controls
{
    [ContentProperty(Name = "Content")]
    public sealed class HeaderControl : Control
    {
        public HeaderControl()
        {
            this.DefaultStyleKey = typeof(HeaderControl);
        }

        public FrameworkElement Header
        {
            get { return (FrameworkElement)GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Header.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeaderProperty =
            DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(HeaderControl), new PropertyMetadata(null));

        public FrameworkElement Content
        {
            get { return (FrameworkElement)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Content.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(FrameworkElement), typeof(HeaderControl), new PropertyMetadata(null));


    }
}

```

ポイントは、DependencyPropertyでプロパティを作る。
[ContentProperty(Name = "Content")]　でXAMLとして、子は、どのプロパティになるかを指定する。


```xml:Generic.xaml
   <Style TargetType="local2:HeaderControl" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local2:HeaderControl">
                    <Grid Background="{TemplateBinding Background}" >
                        <Grid.RowDefinitions>
                            <RowDefinition Height="auto"></RowDefinition>
                            <RowDefinition Height="*"></RowDefinition>
                        </Grid.RowDefinitions>
                        <ContentPresenter Content="{TemplateBinding Header}"></ContentPresenter>
                        <ContentPresenter Grid.Row="1" Content="{TemplateBinding Content}"></ContentPresenter>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
```

Bindingは、「TemplateBinding」を使う。Contentの表示には、「ContentPresenter」を使う。

このようなもの作ることで、使うときは次のように使う。

```xml:
            <myControls:HeaderControl>
                <myControls:HeaderControl.Header>
                    <TextBlock Text="Header"></TextBlock>
                </myControls:HeaderControl.Header>
                <TextBlock Text="Content"></TextBlock>
            </myControls:HeaderControl>
```

これだけの記述で、初めのXAMLと同じことが実現できる。レイアウトのために使う行数は、４行と短くなっており、Header部分、とContent部分がわかりやすいものとなり、捗る。今のところ、\<myControls:HeaderControl.Header>とやっているところが冗長なので、Header部分をテキストだと割り切る形で作れば、２行で済む。
テンプレートコントロールを使い、共通部品化することで、変更や機能追加もやりやすくなる。テンプレートコントロールを使った事例には、アニメーションが多い。

以上は、シンプルな例で、もうちょっと複雑なことは、このソースコードが参考になる。
http://deanchalk.com/a-xaml-uwp-custom-control-the-expander/
https://github.com/deanchalk/ExpanderUWP