Home > Enterprise >  Selecting a data template based on type in UWP
Selecting a data template based on type in UWP

Time:11-12

Given these types

public class TestTypeBase
{
    public string Name { get; set; }
}
public class TestTypeToggle : TestTypeBase
{
}
public class TestType : TestTypeBase
{
    public bool Enabled { get; set; } = false;
}

this data context

public class vm
{
    public ObservableCollection<TestTypeBase> TestTypes { get; } = new ObservableCollection<TestTypeBase> { new TestTypeToggle { Name = "Don't Test" }, new TestTypeToggle { Name = "Always Test" }, new TestType { Name = "qwert", Enabled = true }, new TestType { Name = "qwert", Enabled = true } };
}

(xaml)

<Page.DataContext>
    <local:vm />
</Page.DataContext>

and this view

<ComboBox Width="120" ItemsSource="{Binding TestTypes}">
    <ComboBox.Resources>
        <DataTemplate x:Key="a" x:DataType="local:TestType">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}" />
                <CheckBox IsChecked="{Binding Enabled}" />
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="b" x:DataType="local:TestTypeToggle">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>

i was hoping that the ItemTemplate would be selected based on the item types but all i get are the type names as string.

This solution seems promising but i cannot figure how to give the type hint.

(I'm basically having the same problems as in this question but in a UWP context)

Is this possible or do i have to use a ItemTemplateSelector?

CodePudding user response:

Yes, UWP is different from WPF. You have to use a ItemTemplateSelector in UWP.

Here are the official documents for your reference.

Page.xaml

<Page.Resources>
    <DataTemplate x:Key="NormalItemTemplate" x:DataType="x:Int32">
        <Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemChromeLowColor}">
            <TextBlock Text="{x:Bind}" />
        </Button>
    </DataTemplate>

    <DataTemplate x:Key="AccentItemTemplate" x:DataType="x:Int32">
        <Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}">
            <TextBlock Text="{x:Bind}" />
        </Button>
    </DataTemplate>
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
        Normal="{StaticResource NormalItemTemplate}"
        Accent="{StaticResource AccentItemTemplate}"/>
</Page.Resources>

<Grid>
    <ListView x:Name = "TestListView"
      ItemsSource = "{x:Bind NumbersList}"
      ItemTemplateSelector = "{StaticResource MyDataTemplateSelector}">
    </ListView>
</Grid>

Page.xaml.cs

public sealed partial class MainPage : Page
{
    public ObservableCollection<int> NumbersList = new ObservableCollection<int>();
    public MainPage()
    {
        this.InitializeComponent();

        NumbersList.Add(1);
        NumbersList.Add(2);
        NumbersList.Add(3);
    }
}

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate Normal { get; set; }
    public DataTemplate Accent { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        if ((int)item % 2 == 0)
        {
            return Normal;
        }
        else
        {
            return Accent;
        }
    }
}

Edit

According to this document,

If your ItemsControl.ItemsPanel is an ItemsStackPanel or ItemsWrapGrid, provide an override for the SelectTemplateCore(Object) method. If the ItemsPanel is a different panel, such as VirtualizingStackPanel or WrapGrid, provide an override for the SelectTemplateCore(Object, DependencyObject) method.

So you need override the SelectTemplateCore(Object, DependencyObject) method in your DataTemplateSelector.

Page.xaml

<Page.Resources>
    <DataTemplate x:Key="NormalItemTemplate" x:DataType="x:Int32">
        <TextBox Text="{x:Bind}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemChromeLowColor}" />
    </DataTemplate>

    <DataTemplate x:Key="AccentItemTemplate" x:DataType="x:Int32">
        <TextBox Text="{x:Bind}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}" />
    </DataTemplate>
    
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
        Normal="{StaticResource NormalItemTemplate}"
        Accent="{StaticResource AccentItemTemplate}"/>
</Page.Resources>

<Grid>
    <ComboBox x:Name="Testcombox"
              ItemsSource="{x:Bind NumbersList}"
              ItemTemplateSelector = "{StaticResource MyDataTemplateSelector}">
    </ComboBox>
</Grid>

Page.xaml.cs

public sealed partial class MainPage : Page
{

    public ObservableCollection<int> NumbersList = new ObservableCollection<int>();

    public MainPage()
    {
        this.InitializeComponent();

        NumbersList.Add(1);
        NumbersList.Add(2);
        NumbersList.Add(3);
    }

}


public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate Normal { get; set; }
    public DataTemplate Accent { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        if ((int)item % 2 == 0)
        {
            return Normal;
        }
        else
        {
            return Accent;
        }
    }
}
  • Related