2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TemplateSelectorとDataTriggerを使用した一例

Posted at

はじめに

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

サンプルデータ

    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を以下のように記述します

    <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を以下のように記述します

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

TemplateSelectorクラス作成

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

    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

チェックボックスなどの値でListBoxItemを変更したい場合

さきほどまではListBoxItemの値によって表示を変更する方法でしたが、アプリ開発していると、外部の値によってListBoxItemを変更したいということもあります。
こんな感じの機能です
ListBoxDataTrigger.gif
こういうときはDataTriggerを使用すると簡単に実装できます

View

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

    <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に対して設定すれば、画面内そのものを変更するといったこともできます。
疑似的にページが切り替わったみたいな機能を実装できちゃったりします。

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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?