DZone
Mobile Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Mobile Zone > Different Templates in One Listbox

Different Templates in One Listbox

Andrew Conlisk user avatar by
Andrew Conlisk
·
Apr. 12, 12 · Mobile Zone · Interview
Like (0)
Save
Tweet
4.97K Views

Join the DZone community and get the full member experience.

Join For Free

In this post I will explain how I selected different templates based on the type of data I wanted to show in the same listbox.

Now why might you want 2 different templates in the same list box? Well what if you wanted to display different tasks and appointments for a single day. But you want to see at a quick glance what a task is and what an appointment is. So lets say you have a square for all tasks and a circle for all appointments.

To do this you will use a ContentControl which as the data gets bound to the listbox, we will override the method to check if the item getting bound is a task or appointment. And then set the template depending on what it is.

In my code example the tasks and appointments both inherit from a class called CalendarItem. This is an object orientated programing principle, and if you don’t understand it let me know and I will create a blog about the basics of it.

First think I did was to create the templates I would be using for tasks and appointments. I created a seperate file called “DataTemplates.xaml” and put it into a folder called “Resources”.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataTemplate x:Key="TaskTemplate">
      <StackPanel Orientation="Horizontal" Margin="0, 6">
        <Grid Margin="12, 0, 12, 0">
          <Rectangle Fill="{Binding categoryColor}" Width="20" Height="20"/>
        </Grid>
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding title}" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="24" Width="300"/>
          <TextBlock Text="{Binding time}" HorizontalAlignment="Right" FontSize="24" Width="112"/>
        </StackPanel>
      </StackPanel>
    </DataTemplate>
 
    <DataTemplate x:Key="ApptTemplate">
        <StackPanel Orientation="Horizontal" Margin="0, 6">
            <Grid Margin="12, 0, 12, 0">
                <Ellipse Fill="{Binding categoryColor}" Width="20" Height="20"/>
            </Grid>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding title}" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="24" Width="300"/>
                <TextBlock Text="{Binding time}" HorizontalAlignment="Right" FontSize="24" Width="300"/>
            </StackPanel>
        </StackPanel>
    </DataTemplate>
 
</ResourceDictionary>

As you look at this code you will see the template structures look alike, but one uses a rectangle and the other usues an ellipse. Now in the CalendarItem class everything has a category and a categoryColor, a title and a time. So we us all that data to display.

Next thing is you will have to create the override using the ContentControl. Create a class file in your solution, I called mine “TemplateSelector.cs.”

using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;
using System.Xml.Linq;
 
namespace DuelTemplateSample.Helpers
{
    public class DataTemplateHelper
    {
        public static DataTemplate LoadFromDictionary(string dictionary, string template)
        {
            var doc = XDocument.Load(dictionary);
            var dict = (ResourceDictionary)XamlReader.Load(doc.ToString(SaveOptions.None));
            return dict[template] as DataTemplate;
        }
    }
 
    public class templateSelector : ContentControl
    {
        protected override void OnContentChanged(object oldContent, object newContent)
        {
            base.OnContentChanged(oldContent, newContent);
 
            var calItem = (CalendarItem)newContent;
 
            if (calItem.type == "APPT")
            {
                ContentTemplate = DataTemplateHelper.LoadFromDictionary(
                                "DuelTemplateSample;component/Resources/DataTemplates.xaml",
                                "ApptTemplate");
            }
            else
            {
                ContentTemplate = DataTemplateHelper.LoadFromDictionary(
                                "DuelTemplateSample;component/Resources/DataTemplates.xaml",
                                "TaskTemplate");
            }
        }
    }
}

As you can see in the ContentControl code we are overriding the OnContentChanged method, which takes in 2 objects. oldContent and newContent. If you don’t understand what an override is, it is another principle of object orientated programming. We then typecase (that is setting the object as another type), in this case we are saying the the newContent is a CalendarItem. Then we check the the type is, this is a property of calendar item, it will be either ‘APPT’ for appointment or ‘TASK’ for task. Then depending on what the type is we load the ContentTemplate from the DateTemplate file and the template name. In the code I am calling a method called LoadFromDictionary which is defined in the code above the OnContentChanged. All this does is loads in the xaml file that you created before, and gets the template matching the template name. As you can see I am sending a string that is giving the location of the xaml file, this format is used to tell the location of the file in the application the “DuelTemplateSample;” tells what namespace the file is located in, and the “component/Resources/DataTemplates.xaml” tells that the file is located in the Resources folder. The component means it is in the ‘root’ of the project.

Now is the time to get to set up to work in the ListBox. In your xaml page that will contain the ListBox, add in

xmlns:templateSelector="clr-namespace:DuelTemplateSample.Helpers"

to the PhoneApplicationPage with all the other namespaces. As you can see “DuelTemplateSample.Helpers” is the namespace of where the templateSelector / OnContentChanged is located. Now for the ListBox mine looks like this

<ListBox x:Name="DuelListBox" SelectionChanged="DuelListBox_SelectionChanged" Height="133" Margin="0,475,0,0" VerticalAlignment="Top" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <templateSelector:templateSelector Content="{Binding}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

As you see I set the DataTemplate to

<templateSelector:templateSelector Content="{Binding}"/>

This is what calls the OnContentChange override method and sets the template to the template depending on the type that we coded before.

Now all you need to do is bind a set of data to the ListBox and check out the results. In this case I have a list of CalendarItems a mix of tasks and appointments and load it into the ListBox in the code behind.

I hope this helps and if you are confused, have any questions or comments please comment or email me at andy (at) underbridgecity.net.

 

Template

Published at DZone with permission of Andrew Conlisk, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Enough Already With ‘Event Streaming’
  • How to Test JavaScript Code in a Browser
  • 7 Traits of an Effective Software Asset Manager
  • Ultra-Fast Microservices: When Microstream Meets Wildfly

Comments

Mobile Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo