Question

Being new to the Windows 7/8 phone development arena... I am enjoying working with the windows phone tremendously... however there has been a learning curve and so much to get to know.

With that said, what I am trying to do is create a page that that is dynamically bound to a data structure that will display n number of pivot pages, and each pivot page will have different XAML to display the content.

I looked over this code project article (http://www.codeproject.com/Articles/113152/Applying-Data-Templates-Dynamically-by-Type-in-WP7) and it uses a list box to control the display... but what I am interested in is doing the same thing, but with a pivot page.

I learn best by example... here are the classes for binding the data to the controls, that I would LIKE TO USE ...

  public class ParkingLot : List<Car>
  {
    public ParkingLot() { }

    // this will be the pivot page title
    public string Lot { get; set; }

    // the list of cars will be displayed on the page
  }
  public class Car
  {
    public Car() { }

    // this will be the data that is displayed in the pivot page for each car
    public string Width { get; set; }
    public string Length { get; set; }
  }


  public class Library : List<Book>
  {
    public Library() { }

    // this will be the pivot page title
    public string Location { get; set; }

    // the list of books will be displayed on the page
  }
  public class Book
  {
    public Book() { }

    // this is the data that will be displayed for each book
    public string ISBN { get; set; }
    public string Title { get; set; }
  }

I don't know if it would be better to post all the code here... or just to have you all look at the article on Code project, I will post up the code that I modified from the article... in hopes that somebody can help me figure this out:

xaml :

    <phone:PhoneApplicationPage x:Class="dynDataTemplateTest.MainPage"
                        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
                        xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
                        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                        xmlns:loc="clr-namespace:dynDataTemplateTest.View"

                        xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"

                        FontFamily="{StaticResource PhoneFontFamilyNormal}"
                        FontSize="{StaticResource PhoneFontSizeNormal}"
                        Foreground="{StaticResource PhoneForegroundBrush}"
                        SupportedOrientations="Portrait"
                        Orientation="Portrait"
                        mc:Ignorable="d"
                        d:DesignWidth="480"
                        d:DesignHeight="768"
                        shell:SystemTray.IsVisible="True"
                        DataContext="{Binding Main, Source={StaticResource Locator}}">

<!--LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot"
      Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel"
                Grid.Row="0"
                Margin="24,24,0,12">
        <TextBlock x:Name="ApplicationTitle"
                   Text="{Binding ApplicationTitle}"
                   Style="{StaticResource PhoneTextNormalStyle}" />
        <TextBlock x:Name="PageTitle"
                   Text="{Binding PageName}"
                   Margin="-3,-8,0,0"
                   Style="{StaticResource PhoneTextTitle1Style}" />
    </StackPanel>

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentGrid"
          Grid.Row="1">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <loc:DynamicContentControl Content="{Binding SelectedItem}"
                            HorizontalContentAlignment="Stretch"
                            VerticalContentAlignment="Stretch" />

        <controls:Pivot ItemsSource="{Binding Path=Items}" SelectedItem="{Binding Path=SelectedItem}" >

            <controls:Pivot.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=DisplayName}" FontSize="30" FontWeight="Bold" Margin="5"/>
                </DataTemplate>
            </controls:Pivot.HeaderTemplate>


            <controls:Pivot.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"></StackPanel>
                </ItemsPanelTemplate>
            </controls:Pivot.ItemsPanel>

        </controls:Pivot>

    </Grid>
</Grid>

Here is the DataTemplateSelector class

public static class DataTemplateSelector
{

    public static DataTemplate GetTemplate(ViewModelBase param)
    {
        Type t = param.GetType();
        return App.Current.Resources[t.Name] as DataTemplate;
    }
}

Here is the dynamic Content control: public class DynamicContentControl:ContentControl { protected override void OnContentChanged(object oldContent, object newContent) { base.OnContentChanged(oldContent, newContent); this.ContentTemplate = mSator.Model.DataTemplateSelector.GetTemplate(newContent as ViewModelBase); }
}

Here is the first view xaml:

<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
    <TextBlock Margin="20" Foreground="Green" FontSize="32"
           FontWeight="Bold" Text="{Binding Path=FirstProperty}"
           ></TextBlock>
</Grid>

( the second view xaml can be the first view, just change the color )

Here is the FirstViewModel class (from the article)

    public class FirstViewModel : SelectableViewModel
{
    public FirstViewModel()
    {
        DisplayName = "First";
        FirstProperty = "this is the first property";
    }


    private string firstProp;
    public string FirstProperty
    {
        get { return firstProp; }
        set
        {
            if (firstProp != value)
            {
                firstProp = value;
                RaisePropertyChanged("FirstProperty");
            }
        }
    }

}

Here is the SelectableView Model class

 public class SelectableViewModel : ViewModelBase
 {
    public SelectableViewModel()
    {
    }

    string dispName;
    public string DisplayName
    {
        get { return dispName; }

        set
        {
            if (dispName != value)
            {
                dispName = value;
                RaisePropertyChanged("DisplayName");
            }
        }
    }
}

Here is the main view model class:

    public class MainViewModel : ViewModelBase
{
    public string ApplicationTitle
    {
        get
        {
            return "Dynamic Data Templates";
        }
    }

    public string PageName
    {
        get
        {
            return "Main page";
        }
    }

    private List<SelectableViewModel> viewModels;
    public MainViewModel()
    {
        viewModels = new List<SelectableViewModel>();

        viewModels.Add(new FirstViewModel());
        viewModels.Add(new SecondViewModel());

        SelectedItem = viewModels[0];
    }

    public List<SelectableViewModel> Items
    {
        get
        {
            return viewModels;
        }
    }

    SelectableViewModel selItem;
    public SelectableViewModel SelectedItem
    {
        get { return selItem; }
        set 
        {
            if (selItem != value)
            {
                selItem = value;
                RaisePropertyChanged("SelectedItem");
            }
        }
    }
}

Thanks again for helping !

Was it helpful?

Solution

As you say you're still learning, let me explain why having n number of Pivot items is a bad idea:

  1. You will likely run into performance issues due to the amount of content on a single page. With a list the items can be virtualized. The Pivot control does not support virtualization of dynamically added PivotItems.

  2. It's hard for people to navigate to a desired item when there are lots of PivotItems as there isn't a way to quickly get to the one that is wanted. Say you had 30 items in the pivot but wanted to get to the 15th one. That would require a lot of swiping and if doing it quickly it would be easy to go past the one that was wanted.

The Pivot Control is intended to be used for one of two purposes:

  1. To show different views of a set of data. i.e. The email app shows different views of a mailbox in each PivotItem, filtered for "all", "unread", "flagged" and "urgent".

  2. To show different pieces of related data. i.e. When viewing an individual contact/person you see different related actions and information grouped into the different PivotItems: "profiles", "what's new", "photos" and "history".

It is not the intention that the Pivot control should be used as a container for vast quantities of content, such as n collections of template lists.
It is suggested that the maximum number of items in a pivot should be 7 to avoid issues with performance and usability.

All in all, not using the Pivot control in one of the ways it was intended can cause performance issues for you as a developer and usability issues for the people using the app.
Both of which are scenarios to be avoided.

Sorry this isn't a direct answer to your question but hopefully it will help you develop a better app (or apps). ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top