views:

384

answers:

1

I have a hierarchy of view models representing formatted content:

public abstract class ContentPartViewModel : ViewModel
{
}

public class TextContentPartViewModel : ContentPartViewModel
{
    public string Text { ... }
}

public class TitleContentPartViewModel : TextContentPartViewModel
{
}

public class HyperlinkContentPartViewModel : TextContentPartViewModel
{
    public string Uri { ... }
}

I have an encompassing view model that contains a collection of ContentPartViewModels to be rendered:

public class ContentViewModel
{
    public ICollection<ContentPartViewModel> ContentParts { ... }
}

I then have a ContentView that renders all parts of the content:

<UserControl ...>
    <ItemsControl ItemsSource="{Binding ContentParts}"/>
</UserControl>

In an ideal world, I would just define a DataTemplate for each of the content part types and they would be rendered accordingly. However, Silverlight does not support the DataType property on the DataTemplate class, so that is not an option.

Another option would be to provide a DataTemplateSelector and do the mapping from view model type to DataTemplate myself. Alas, ItemsControl in SL2 does not have an ItemTemplateSelector property - only an ItemTemplate property.

That left me with no option but to provide an ItemTemplate that then uses a converter to turn off all the UI apart from the piece relevant to that content part:

<ItemsControl.ItemTemplate>
 <DataTemplate>
  <Grid>
   <TextBlock Text="{Binding Text}" FontWeight="Bold" Visibility="{Binding Converter={StaticResource TitleContentPartConverter}}"/>

   <TextBlock Text="{Binding Text}" Visibility="{Binding Converter={StaticResource TextContentPartConverter}}"/>

   <HyperlinkButton Content="{Binding Text}" NavigateUri="{Binding Uri}" Visibility="{Binding Converter={StaticResource HyperlinkContentPartConverter}}"/>
  </Grid>
 </DataTemplate>
</ItemsControl.ItemTemplate>

This is obviously rather awful, both for performance and for readability/correctness of code. It also makes it much harder for me to format the output correctly. So, questions:

  1. Can anyone recommend a better way to do this in SL2?
  2. Can anyone confirm whether the situation has improved in SL3?

Thanks, Kent

+1  A: 
  1. Yes. DataType in DataTemplate is not supported in Silverlight 2 or Silverlight 3.

  2. You can work around ItemTemplateSelector in Silverlight. Please take a look at this sample.

http://silverlight.net/forums/t/12598.aspx

protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
    base.PrepareContainerForItemOverride(element, item); 
    DataTemplateSelector selector = this.ItemTemplateSelector;

    if (null != selector)
    {
        ((ContentPresenter)element).ContentTemplate = selector.SelectTemplate(item, element);
    }
}
Michael Sync
Thanks Michael. Not ideal that I have to create all that infrastructure and subclass various ItemsControls myself, but seems like it should work. Will update once I've tried it.
Kent Boogaart
The sample nor this question isn't really complete w/o this link too: http://forums.silverlight.net/forums/t/79266.aspx That shows you how to define the DataTemplate resources and reference them programmatically.
xanadont