WPF MVVM Создание динамических элементов управления - PullRequest
8 голосов
/ 11 марта 2011

WPF MVVM Создание динамических элементов управления - у меня есть сетка, на которой у меня есть детали задания (можно сказать что-то вроде задания сервера sql).

Теперь для каждой работы может быть 'n' количество переменных работы.Когда я выбираю запись для задания, он получает эту коллекцию переменных Job, которые представляют собой пару имя-значение, где value может быть коллекцией или значением datetime или даже int или строкой.

Теперь я пытаюсь достичь следующего: - Если переменная запуска является datetime, тогда мне нужен DatePicker - Если это int / String, мне нужно текстовое поле - Если этоКоллекция затем поле со списком.- если это битовое поле, то флажок

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

Ответы [ 2 ]

9 голосов
/ 11 марта 2011

Я предполагаю, что вы поместите какой-то объект, представляющий эти пары имя / значение, в ItemsControl, установив его свойство ItemsSource.

Есть несколько решений, которые вы можете использовать.

Использование DataTemplate с триггерами:

Этот подход включает в себя выставление "типа" каждого из ваших объектов через свойство YourPropertyType в виде строки. Вы установите ItemTemplate вашего ItemsControl на шаблон, в котором находится ContentControl. У самого ContentControl будет ContentTemplate, выбранный динамически с помощью триггеров.

Все это можно сделать декларативно в XAML.

Я предполагаю, что у вас есть еще DataTemplates с именем DefaultTemplate (это может быть пустым), IntegerTemplate, StringTemplate и т. Д., Чтобы набросать визуальное дерево для каждого случая.

Тогда это будет ItemsControl.ItemTemplate:

<DataTemplate>
    <ContentControl
        x:Name="MyContentControl"
        Content="{Binding}"
        ContentTemplate="{StaticResource DefaultTemplate}"/>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding YourPropertyType}" Value="Integer">
            <Setter TargetName="MyContentControl" Property="ContentTemplate"
                    Value="{StaticResource IntegerTemplate}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding YourPropertyType}" Value="String">
            <Setter TargetName="MyContentControl" Property="ContentTemplate"
                    Value="{StaticResource StringTemplate}" />
        </DataTrigger>
        <!-- and so on -->
    </DataTemplate.Triggers>
</DataTemplate>

Использование DataTemplateSelector:

Этот подход требует выделенного кода, но он не заставляет вас раскрывать «тип» каждой пары имя / значение в виде строки и позволяет выбирать, какой шаблон использовать с гораздо более сложной логикой.

Включает создание класса для выбора шаблона:

class YourObjectDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var yourObject = (YourObjectType) item;

        // Get hold of a DataTemplate based on any attribute of item
        var templateToUse = this.DefaultTemplate;

        return templateToUse;
    }
}

Затем вам нужно где-то создать экземпляр шаблона (скажем, внутри вашего UserControl)

<UserControl.Resources>
    <localNamespace:YourObjectDataTemplateSelector
      x:Key="TemplateSelector"
      DefaultTemplate="{StaticResource DefaultTemplate}"
    />
</UserControl.Resources>

Обратите внимание, что я выставил свойство DefaultTemplate из YourObjectDataTemplateSelector и установил для него шаблон из XAML. На практике вы определяете больше свойств типа DataTemplate для YourObjectDataTemplateSelector и «настраиваете» селектор шаблона при добавлении его в словарь ресурсов вашего элемента управления. Это позволяет вам напрямую устанавливать шаблоны для каждого случая, используя расширение разметки StaticResource из XAML.

Наконец, подключите селектор шаблонов к вашему ItemsControl:

<ItemsControl 
  ItemsSource="..."
  ItemTemplateSelector={StaticResource TemplateSelector}"
/>
2 голосов
/ 11 марта 2011

Я полагаю, что вы собираетесь использовать некоторую форму Data Templating и DataTemplateSelector для достижения того, чего вы хотите.

...