DataTemplate. Альтернатива DataType в Silverlight

У меня есть модель представления со свойством 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 не имеет a DataType свойство. Я озадачен. Каков путь Silverlight сделать это?

14
задан Alex 8 March 2010 в 10:11
поделиться

3 ответа

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

<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}"/>

in 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;

}
7
ответ дан 1 December 2019 в 12:26
поделиться

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;
        }
    }
}
3
ответ дан 1 December 2019 в 12:26
поделиться

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

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

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

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

<ListBox ItemTemplate="{StaticResource DynamicTemplate}">

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

4
ответ дан 1 December 2019 в 12:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: