locked
Need help implementing DataTemplate Selector.

    Question

  • Hi everyone,

    I have made a simple RSS Feed app using AppStudio, and as the title suggests, I need some help on implementing DataTemplateSelector.

    I want the first and the last items of the feed to use "BigCards" item template, while the others to have the "SmallCards" item template. 

    Here is the code for the item template styling:
    <!-- BigCard Item -->
        <DataTemplate x:Key="BigCards">
            <Grid Style="{StaticResource BoxGrid}" Margin="0,0,0,10" Height="380">
                <Rectangle Width="900"/>
                <Grid Style="{StaticResource BoxGrid}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="280"/>
                        <RowDefinition Height="220"/>
                    </Grid.RowDefinitions>
                    <Image Grid.Row="0" Source="{Binding ImageUrl}" Stretch="UniformToFill" Margin="0,4,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    <Grid Grid.Row="1" Height="220" Margin="10,10,10,10">
                        <Grid Height="210">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Row="0" Style="{StaticResource BoxTitleStyle}" Text="{Binding Title}" MaxLines="2"/>
                        </Grid>
                    </Grid>
                </Grid>
            </Grid>
        </DataTemplate>
    
        <!-- ListHorizontalCards Item -->
        <DataTemplate x:Key="SmallCards">
            <Grid Height="120" Margin="0,0,0,10" Style="{StaticResource BoxGrid}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="120"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Image Source="{Binding ImageUrl}" Stretch="UniformToFill" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                <Grid Grid.Column="1">
                    <Rectangle Width="900" Height="0"/>
                    <Grid Margin="16,5,16,5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <TextBlock Grid.Row="0" Style="{StaticResource BoxTitleStyle}" Text="{Binding Title}" MaxLines="2"/>
                        <TextBlock Grid.Row="1" Margin="0,5,0,0" Style="{StaticResource BoxSubtitleStyle}" Text="{Binding Summary}"/>
                    </Grid>
    
                </Grid>
            </Grid>

    Here is the .cs of the MainPage:

            //Listim dinamik i artikujve
    
            public abstract class TemplateSelector : ContentControl
            {
                public abstract DataTemplate SelectTemplate(object item, DependencyObject container);
    
                protected override void OnContentChanged(object oldContent, object newContent)
                {
                    base.OnContentChanged(oldContent, newContent);
    
                    ContentTemplate = SelectTemplate(newContent, this);
                }
            }
    
            //endof Abstract Class
    
            public class ArticleTemplateSelector : TemplateSelector
            {
                public DataTemplate BigCards
                {
                    get;
                    set;
                }
    
                public DataTemplate SmallCards
                {
                    get;
                    set;
                }
    
    
              public override DataTemplate SelectTemplate(object item, DependencyObject container)
              {
                    // Determine which template to return;
    
                    return null;
                }
            }
    I would really appreciate if someone could help me on what I should insert in the DataTemplate SelectTemplate class...?
    "return null" is there just so the class gets a result as its required, so that is not neccesarily needed there.

    Here is the Main Page xaml which as for the moment uses the BigCards template:
     <Hub x:Name="Container" Grid.Row="1" Margin="0,28,0,0" Background="{StaticResource AppBackground}" DataContext="{Binding}" SectionsInViewChanged="OnSectionsInViewChanged">
                        <HubSection x:Name="LajmetSection" Padding="0,-30,20,0" Width="400" DataContext="{Binding MainViewModel.LajmetModel}"
                            d:DataContext="{d:DesignData Source=/Assets/Data/LajmetDataSource.json, Type=vm:LajmetViewModel, IsDesignTimeCreatable=true}"
                            ContentTemplate="{StaticResource BigCards}" IsHeaderInteractive="{Binding HasMoreItems}" />
                    </Hub>

    • Edited by as__ Friday, May 8, 2015 9:06 AM mixed up variables in datatemplate and in mainpage cs(fixed)
    Thursday, May 7, 2015 6:56 PM

All replies

  • You'll need to determine if you want the BigCards or the SmallCards template based on the item and then return the appropriate template. How to decide between them is up to the app.

    Often a good way to manage the templates is to expose properties for the two templates which the DataTemplateSelector can then return (it looks like you already have those). The properties can be set from Xaml so you don't need to hardcode the actual templates in code-behind.

    Set up the ArticleTemplateSelector with the two templates. It can then be set in the control that will use it:

    <Page.Resources>
         <local:ArticleTemplateSelector x:Key="articleSelector" LajmetItem="{StaticResource BigCards}" RssItem="{StaticResource SmallCards}" />
    </Page.Resources>
    And in the code behind choose between the templates based on the item. How to choose is up to the app:
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
       // Determine which template to return;
       if (ShouldUseBigTemplate(item))
       {
           return LajmetItem;
       } 
       else 
       {
           return RssItem;
       }
    
       return null;
    }

    Thursday, May 7, 2015 10:36 PM
    Moderator
  • LajmetItem and RssItem are irrelevant. Sorry for not changing them in the first place. Take a look at the edited post please. And I don't want app to determine which template to use. I want the first and last item to be using BigCards, and the other ones SmallCards.

    Kind Regards
    Friday, May 8, 2015 9:08 AM