TemplateSelectorとDataTriggerを使用した一例

#はじめに
WPFでListBoxを使用した際に、データによって表示を変更したいことがあります。
そんなときは、TemplateSelectorを使用します。

##サンプルデータ

```C#
    public class SampleData
    {
        public int ID { get; set; }
        public string SampleText { get; set; }
        public string SampleText2 { get; set; }
    }

    public ObservableCollection<SampleData> SampleDatas

    private void SetDatas()
    {
        SampleDatas = new ObservableCollection<SampleData>();
        for (int i = 0; i < 10; i++)
        {
            SampleDatas.Add(new SampleData()
            {
                ID = i,
                SampleText = $"さんぷるてきすと{i}",
                SampleText2 = $"サンプルテキスト{i}"
            });
        }
    }

```
これをたとえばIDの値によって表示するTextや文字色を変更してみます

##View
Window.Resourcesを以下のように記述します

```C#
    <Window.Resources>
        <DataTemplate x:Key="IsChekedTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding ID}"
                           Foreground="Red"/>
                <TextBlock Text="{Binding SampleText}"
                           Foreground="Red"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="IsNotChekedTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding ID}"
                           Foreground="Blue"/>
                <TextBlock Text="{Binding SampleText2}"
                           Foreground="Blue"/>
            </StackPanel>
        </DataTemplate>
```

次にListBoxを以下のように記述します

```C#
    <ListBox ItemsSource="{Binding SampleDatas}">
        <ListBox.ItemTemplateSelector>
            <local:ListBoxTemplateSelector
                   IsChekedTemplate="{StaticResource IsChekedTemplate}"
                   IsNotChekedTemplate="{StaticResource IsNotChekedTemplate}"/>
        </ListBox.ItemTemplateSelector>
    </ListBox>
```

##TemplateSelectorクラス作成
以下のようにListBoxTemplateSelector を作成します
ここではIDの値が2で割り切れるかどうかで判別しています

```C#
    public class ListBoxTemplateSelector : DataTemplateSelector
    {
        public DataTemplate IsChekedTemplate { get; set; }
        public DataTemplate IsNotChekedTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item == null) return IsNotChekedTemplate;

            var id = ((SampleData)item).ID;

            if (id % 2 == 0)
            {
                return IsChekedTemplate;
            }
            else
            {
                return IsNotChekedTemplate;
            }
        }
    }
```

実行するとこんな感じになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/d4c2b0a6-d8c0-fbf2-efc1-711b12204f00.png)

#チェックボックスなどの値でListBoxItemを変更したい場合
さきほどまではListBoxItemの値によって表示を変更する方法でしたが、アプリ開発していると、外部の値によってListBoxItemを変更したいということもあります。
こんな感じの機能です
![ListBoxDataTrigger.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/e6b5d024-6907-1601-0867-20837be127fe.gif)
こういうときはDataTriggerを使用すると簡単に実装できます

##View
ここではViewModelは使用せずに機能するようにしています

```C#
    <ListBox ItemsSource="{Binding SampleDatas}">
        <ListBox.Style>
            <Style TargetType="ListBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=IsCheckByDataTrigger, Path=IsChecked}"
                                    Value="True">
                        <Setter Property="ItemTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="{Binding ID}"
                                                    Margin="0,0,10,0"/>
                                        <TextBlock Text="{Binding SampleText}"/>
                                    </StackPanel>
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding ElementName=IsCheckByDataTrigger, Path=IsChecked}"
                                    Value="False">
                        <Setter Property="ItemTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="{Binding ID}"
                                                    Foreground="Blue"
                                                    Margin="0,0,10,0"/>
                                        <TextBlock Text="{Binding SampleText2}"
                                                    Foreground="Blue"/>
                                    </StackPanel>
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
```

ListBoxのStyle設定からDataTriggerを使用し、ItemTemplateを動的に変更できるようにしています。


今回はListBoxを例に挙げましたが、ContentControlに対して設定すれば、画面内そのものを変更するといったこともできます。
疑似的にページが切り替わったみたいな機能を実装できちゃったりします。

多用するとコードがごちゃごちゃするので気を付ける必要がありますが、覚えておくと結構便利かなと思います。