JokerMartini
JokerMartini

Reputation: 6157

Use data template based on property

Is it possible to control which DataTemplate a node used based on a property rather than the class type which is typically seen in wpf.

In my case I have a list of teams and I want to control the background of each team being listed in the listbox as well as a few other design elements such as displaying different logos based on which team. In my mind it seems easiest to just make a data template based on the team name.

How do you guys suggest I handle it. I don't want to create a class object for every entire team. However it would be ideal if a team doesn't have a design template that a default one gets used.

Either way if someone could put together a super simple example Id appreciate it considering im not sure how to do it .

Upvotes: 1

Views: 76

Answers (1)

SamTh3D3v
SamTh3D3v

Reputation: 9944

From what you described, it seems to me that those property can be hold on the Team class and you could display the content based on them !, but since you might need something much complicated you could use a DataTemplateSelector basically what you need to do is :

First : In resources area define the DataTemplates that you need plus a default one, in case none of the teams names matche a difined template,

lets say something like that :

  <Window.Resources> 
    <DataTemplate x:Key="DefaultnDataTemplate" DataType="{x:Type YourNameSpace:Team}">
        <Grid Background="LightGreen">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Text="DefaultnDataTemplate"/>
            <TextBlock Text="{Binding Id}" Grid.Row="1" Grid.Column="0"/>
            <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
            <TextBlock Text="{Binding Matches}" Grid.Row="1" Grid.Column="2"/>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="TeamADataTemplate" DataType="{x:Type YourNameSpace:Team}">
        <Grid Background="LightCoral">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Text="TeamADataTemplate"/>
            <TextBlock Text="{Binding Id}" Grid.Row="1" Grid.Column="0"/>
            <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
            <TextBlock Text="{Binding Matches}" Grid.Row="1" Grid.Column="2"/>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="TeamBDataTemplate" DataType="{x:Type YourNameSpace:Team}">
        <Grid Background="LightBlue">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Text="TeamBDataTemplate"/>
            <TextBlock Text="{Binding Id}" Grid.Row="1" Grid.Column="0"/>
            <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
            <TextBlock Text="{Binding Matches}" Grid.Row="1" Grid.Column="2"/>
        </Grid>
    </DataTemplate>        
</Window.Resources>

Second add a DataTemplateSelector class, the class will basically check the team name and return the appropriate DataTemplate:

 public class TeamDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultnDataTemplate { get; set; }
    public DataTemplate TeamADataTemplate { get; set; }
    public DataTemplate TeamBDataTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item,
               DependencyObject container)
    {
        var teamName = (item as Team).Name;
        switch (teamName)
        {
            case "TeamA":
                return TeamADataTemplate;
            case "TeamB":
                return TeamBDataTemplate;
            default:
                return DefaultnDataTemplate;
        }

    }
}

Third, add an instance of that class to the StaticResources, and point it to the already defined DataTemplates :

 <YourNameSpace:TeamDataTemplateSelector x:Key="TeamDataTemplateSelector" TeamADataTemplate="{StaticResource TeamADataTemplate}" TeamBDataTemplate="{StaticResource TeamBDataTemplate}" DefaultnDataTemplate="{StaticResource DefaultnDataTemplate}"/>

Finally call the TemplateSelector in your List:

<ListBox ItemsSource="{Binding Teams}" ItemTemplateSelector="{StaticResource TeamDataTemplateSelector}">       
</ListBox>

here the model i am using in this sample :

public class Team
{
    public string Name { get; set; }
    public string Id { get; set; }
    public string Matches { get; set; }
}
  private ObservableCollection<Team> _teams=new ObservableCollection<Team>()
    {
        new Team()
        {
            Id="1",
            Matches = "45",
            Name = "TeamA"
        },
        new Team()
        {
            Id="1",
            Matches = "45",
            Name = "TeamB"
        },
        new Team()
        {
            Id="1",
            Matches = "45",
            Name = "TeamC"
        }
    };



    public ObservableCollection<Team> Teams
    {
        get
        {
            return _teams;
        }

        set
        {
            if (_teams == value)
            {
                return;
            }

            _teams = value;
            OnPropertyChanged();
        }
    }

Upvotes: 1

Related Questions