This second example looks at using a collection of viewmodels to dynamically populate a Pivot
using a DataTemplate
. The result of this example is the same as the previous example, except in this case the PivotItems
are dynamically created based on their data type. This provides some added flexibility that can be useful in larger apps.
The example code for this section is located in the files DataboundPivotView.xaml, DataboundPivotView.xaml.cs, and DataboundPivotViewModel.cs in the downloadable sample code.
In this example the viewmodel has been changed from exposing two child viewmodel properties to a collection of viewmodels (see Listing 11.5).
public class DataboundPivotViewModel : ViewModelBase
{
public DataboundPivotViewModel() : base("Databound Pivot")
{
MockChatService chatService = new MockChatService();
items.Add(new MessagesViewModel(chatService));
items.Add(new SendMessageViewModel(chatService));
}
readonly ObservableCollection<ViewModelBase> items
= new ObservableCollection<ViewModelBase>();
public ObservableCollection<ViewModelBase> Items
{
get
{
return items;
}
}
}
By using this approach you can dynamically add and remove content via the main viewmodel. Depending on the data type of the viewmodel, a particular DataTemplate
is resolved from the application’s Resources
collection. This is done using a custom ContentControl
called TypeTemplateSelector
(see Listing 11.6).
public class TypeTemplateSelector : ContentControl
{
protected override void OnContentChanged(
object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
if (newContent == null)
{
return;
}
Type newContentType = newContent.GetType();
ContentTemplate = Application.Current.Resources[
newContentType.Name + "Template"] as DataTemplate;
}
}
The TypeTemplateSelector
attempts to resolve the DataTemplate
for the viewmodels by applying the naming convention [data type]Template. This simplifies our main view, whose XAML is shown in Listing 11.7.
<Grid x:Name="LayoutRoot" Background="Transparent">
<controls:Pivot Title="Windows Phone 8 Unleashed"
ItemsSource="{Binding Items}">
<controls:Pivot.Background>
<ImageBrush ImageSource="../../../Images/PivotBackground.png"/>
</controls:Pivot.Background>
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<p:TypeTemplateSelector Content="{Binding}"
VerticalAlignment="Top"
HorizontalAlignment="Left" />
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
</Grid>
The DataTemplates
are placed in the application resources using the App.xaml file. Contained within the App.xaml file is the SendMessageViewModelTemplate
, which is used to present the SendMessageViewModel
, shown in the following excerpt:
<DataTemplate x:Key="SendMessageViewModelTemplate">
<StackPanel Width="400">
<u:AppBar>
<u:AppBarIconButton
Command="{Binding SendCommand}"
Text="Send"
IconUri="/Images/ApplicationBarIcons/AppBarMessageSend.png"/>
</u:AppBar>
<TextBlock Text="user"
Style="{StaticResource PhoneTextTitle3Style}" />
<TextBox InputScope="EmailSmtpAddress"
Text="{Binding EmailAddress, Mode=TwoWay}" />
<TextBlock Text="message"
Style="{StaticResource PhoneTextTitle3Style}" />
<TextBox Text="{Binding MessageBody, Mode=TwoWay}"
TextWrapping="Wrap"
Height="300" />
<TextBlock Text="{Binding Feedback}"
Style="{StaticResource PhoneTextAccentStyle}"
Margin="12,30,12,0" />
</StackPanel>
</DataTemplate>
In addition, the MessageViewModel
is presented using the MessageViewModelTemplate:
<DataTemplate x:Key="MessagesViewModelTemplate">
<StackPanel>
<u:AppBar>
<u:AppBarIconButton
Command="{Binding RefreshCommand}"
Text="Refresh"
IconUri="/Images/ApplicationBarIcons/AppBarRefresh.png"/>
</u:AppBar>
<ListBox ItemsSource="{Binding MessageItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Body}"
Style="{StaticResource PhoneTextNormalStyle}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Text="{Binding Feedback}"
Style="{StaticResource PhoneTextAccentStyle}"
Margin="12,30,12,0" />
</StackPanel>
</DataTemplate>
3.12.123.189