views:

54

answers:

2

I have a xaml page that has an ItemsControl control on it. ItemsControl is bound to Guests which is ObservableCollection. Guests collection can have objects of two different types: USGuest and UKGuest, both inheriting from Guest. Is it possible to make two (or more) templates for ItemsControl and make it automatically choose between them depending on the run-time type of the current item in collection?

+1  A: 

I haven't tried this, but have you tried to set the ItemsSource to a ObservableCollection of Guest objects and the set the DataTemplate for both types?

<DataTemplate DataType="{x:Type my:USGuestViewModel}">
    <my:USGuestView/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:UKGuestViewModel}">
    <my:UKGuestView/>
</DataTemplate>

EDIT: 'my' is a declaration of the namespace where your ViewModels and Views live, so you should add something like this in the beggining of the xaml:

<UserControl x:Class="my.namespace.SuperView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:my.namespace">

I've checked and you cannot set two DataTemplates in the ItemTemplate property. But you can set them in your UserControl Resources Property:

<UserControl.Resources>
    <DataTemplate DataType="{x:Type my:USGuestViewModel}">
        <my:USGuestView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type my:UKGuestViewModel}">
        <my:UKGuestView/>
    </DataTemplate>
</UserControl.Resources>
jpsstavares
+1, that's probably the best way to do it. Just put these templates in the ItemsControl's resources
Thomas Levesque
I added templates in ItemControl's resources and I'm having build error 'The member "DataType" is not recognized or accessible'. Did I mention I'm working on a Silverlight 4 project? Is all this possible in Silverlight?
77v
I think it is although there are some methods that are not present in Silverlight. I don't think it's the case. I'll edit the post with a more complete code Snippet
jpsstavares
In Silverlight, DataTemplate has no DataType property.
MojoFilter
Sorry, didn't knew about that. Is there any workaround silverlight users use to surpass that?
jpsstavares
Silverlight doesn't have template selectors, so your best bet is to work around it by including two panels in your item template, with their visibility set to some flag on your base Guest class.
Matt Casto
+1  A: 

Sorry, I didn't mean to be a party pooper and not offer a solution. But this is one of the biggest hurdles I run into when using MVVM in Silverlight.

One thing I've done in the past is use a UserControl with just a ContentPresenter inside as the ItemsTemplate. (So many layers!) In the UserControl, when the DataContext changes, I would chose a template to use from the resources of the UserControl. (The templates would not actually have to be inside the UserControl, but I like that encapsulation the best.)

MainPage:

<UserControl>

  <UserControl.Resources>
    <DataTemplate x:key="itemTemplate">
      <my:ItemView />
    </DataTemplate>
  </UserControl.Resources>

  <ItemsControl ItemTemplate="{StaticResource itemTemplate}" />
</UserControl>

ItemView.xaml:

<UserControl>
  <UserControl.Resources>
    <DataTemplate x:Key="Template1">
      <!-- Template #1 -->
    </DataTemplate>
    <DataTemplate x:Key="Template2">
      <!-- Template #2 -->
    </DataTemplate>
  </UserControl.Resources>

  <ContentPresenter Name="presenter"
                    Content="{Binding}" />

</UserControl>

ItemView.xaml.cs

...
OnDataContextChanged(...)
{
  var content = this.DataContext as MyDataType;
  DataTemplate template;
  switch (content.State) 
  {
    case State1:
      template = this.Resources["template1"] as DataTemplate;
      break;
    case State2:
      template = this.Resources["template2"] as DataTemplate;
      break;
  }
  this.presenter.ContentTemplate = template;
}
...

And if you're still following along, note that Silverlight also doesn't provide an OnDataContextChanged method like you get in WPF. So, to cover that, see what Jeremy Likness says about it over here:

http://www.codeproject.com/Articles/38559/Silverlight-DataContext-Changed-Event.aspx

I use that pretty often. Thanks, Jeremy!

Also, there are some pretty severe limitations to this as well, when compared to all of the power that WPF gives you in that arena. For instance, there really is no good way do fake a ItemContainerStyle Selector. (That I know of.)

MojoFilter