Альтернатива DataTemplate.DataType в Silverlight - PullRequest
14 голосов
/ 08 марта 2010

У меня есть модель представления со свойством Fields, которое является ObservableCollection<FieldVM>. В представлении, которое использует это свойство, у меня есть ItemsControl примерно так:

...
<ItemsControl ItemsSource="{Binding Fields}" />
...

FieldVM - абстрактный класс, реализованный такими классами, как TextFieldVM и EnumFieldVM. Во время выполнения эти FieldVM -имплементации добавляются в свойство Fields, и я хочу, чтобы они отображались в моем представлении со своими связанными представлениями.

В WPF сделать это просто, я делаю это все время. Вы просто делаете это в соответствующем словаре ресурсов, и все работает как положено:

<DataTemplate DataType="{x:Type vm:TextFieldVM}">
    <v:TextFieldView />
</DataTemplate>

<DataTemplate DataType="{x:Type vm:EnumFieldVM}">
    <v:EnumFieldView />
</DataTemplate>

Теперь, работая в Silverlight впервые, я ожидал, что смогу сделать то же самое, но у DataTemplate нет свойства DataType. Я в тупике. Что Silverlight-способ сделать это?

Ответы [ 7 ]

8 голосов
/ 24 января 2011

Библиотека Microsoft Prism имеет собственную реализацию DataTemplateSelector, обратите внимание на Имена классов в DataTemplate x: keys:

                    <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <prism:DataTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch" IsTabStop="False">
                            <prism:DataTemplateSelector.Resources>
                                <DataTemplate x:Key="OpenQuestionViewModel">
                                    <Views:OpenQuestionView DataContext="{Binding}"/>
                                </DataTemplate>

                                <DataTemplate x:Key="MultipleSelectionQuestionViewModel">
                                    <Views:MultipleSelectionView DataContext="{Binding}"/>
                                </DataTemplate>

                                <DataTemplate x:Key="NumericQuestionViewModel">
                                    <Views:NumericQuestionView DataContext="{Binding}"/>
                                </DataTemplate>
                            </prism:DataTemplateSelector.Resources>
                        </prism:DataTemplateSelector>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
7 голосов
/ 08 марта 2010

Используйте конвертер значений, чтобы привязать тип к видимости каждого представления:

<DataTemplate> 
    <Grid>
        <v:EnumFieldView 
            Visibilty="{Binding Converter={StaticResource ViewVisibilityConverter}, ConverterParameter=Enum}" /> 
        <v:TextFieldView 
            Visibilty="{Binding Converter={StaticResource ViewVisibilityConverter}, ConverterParameter=Text}" />
    </Grid
</DataTemplate> 

А в ConvertTo ViewVisibilityConverter переключите видимость в зависимости от типа.

Другой способ посмотреть на это - использовать конвертер значений другого типа для возврата другого шаблона данных из Application.Resources.

<ListBox ItemTemplate="{Binding Converter={StaticResource ItemTemplateFactory}"/>

в ItemTemplateFactory.Convert ():

var fieldVM = value as FieldVM;

switch fieldVM.FieldType:
{
    case "Text":
         return Application.Current.Resources["TextTemplate"] as DataTemplate;

    case "Enum":
         return Application.Current.Resources["EnumTemplate"] as DataTemplate;

}
5 голосов
/ 10 августа 2011

Silverlight 5 наконец-то включит эту функциональность. До тех пор отмеченный ответ - один из лучших способов, которые я видел.

4 голосов
/ 25 августа 2010

Вариант на втором варианте от Михаэля (поскольку я не мог заставить его работать напрямую).

В ресурсах определите дополнительный шаблон данных:

<DataTemplate x:Key="DynamicTemplate">
  <ContentPresenter ContentTemplate="{Binding Converter={StaticResource TemplateChooser}}" Content="{Binding}"/>
</DataTemplate>

И затем используйте этот шаблон данныхв списке

<ListBox ItemTemplate="{StaticResource DynamicTemplate}">

TemplateChooser должен быть IValueConvertor, где функция Convert берет объект и возвращает DataTemplate, который должен использоваться для этого объекта.

3 голосов
/ 09 июля 2010

Silverlight не имеет DataTemplateSelector, но я использовал этот фрагмент ...

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <client:TemplateSelector Content="{Binding}"/>
    </DataTemplate>
</ItemsControl.ItemTemplate>

Вот селектор шаблонов:

public class TemplateSelector : ContentControl
{
    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        MyObject f = newContent as MyObject;

        switch (f.MyProperty)
        {
            case "Bool":
            case "String":
            case "Array":
            default:
                ContentTemplate = Application.Current.Resources["MultiSelectDataTemplate"] as DataTemplate;
                break;
        }
    }
}
0 голосов
/ 30 марта 2012

Это сообщение в блоге: http://www.c -sharpcorner.com / Blogs / 1937 / представляет то, что выглядит как хороший селектор шаблонов данных "сделай сам", маскирующийся под конвертер значений.Преимущество заключается в том, что нет необходимости устанавливать Prism.

0 голосов
/ 24 января 2011

Вы пытались пренебречь свойством DataType? и просто напишите что-то вроде этого:

<DataTemplate>
    <v:TextFieldView />
</DataTemplate>

работал для меня

...