Как добавить DataTemplate в CollectionContainer?

#c# #wpf #datatemplate

#c# #wpf #datatemplate

Вопрос:

Вот мой конкретный сценарий.

Окно ресурсов кода:

 ...
<Window.Resources>
    <ResourceDictionary>
        <CollectionViewSource x:Key="AdditionalStringData" Source="{Binding ViewModelObservableCollection_String}"/>
        <CollectionViewSource x:Key="AdditionalCustomObjectData" Source="{Binding ViewModelObservableCollection_CustomObject}"/>
        <ResourceDictionary.MergedDictionaries>
            ...
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
...
  

Часть, в которой мне нужно отобразить коллекцию:

 ...
<StackPanel>
    <ItemsControl>
        <ItemsControl.ItemsSource>
            <CompositeCollection>
                <TextBlock Text="{Binding ViewModelTextProperty}"/>
                <Button Command="{Binding ViewModelRelayCommand}">Command</Button>
                <CollectionContainer Collection="{Binding Source={StaticResource AdditionalStringData}}" />
                <CollectionContainer Collection="{Binding Source={StaticResource AdditionalCustomObjectData}}" />
            </CompositeCollection>
        </ItemsControl.ItemsSource>
    </ItemsControl>
</StackPanel>
...
  

ViewModel (предположим, что он привязан правильно)

 ...
private string ViewModelTextProperty  { get; set; } = "Sample Text";
public RelayCommand ViewModelRelayCommand { ... }
private ObservableCollection<string> ViewModelObservableCollection_String { get; set; } = new ObservableCollection<string>();
private ObservableCollection<CustomObject> ViewModelObservableCollection_CustomObject { get; set; } = new ObservableCollection<CustomObject>();
...
  

Класс CutomObject (возможно, он не нужен для отображения):

 ...
public class CustomObject
{
    public string firstString;
    public string secondString;

    public CustomObject()
    {
        ...
    }
    ...
}
...
  

Предположим, что ObservableCollection s имеет правильное содержимое.

Мой вопрос: как я могу правильно отобразить коллекцию? Вот критерии:

  • В первой строке будет текстовый блок с текстом внутри него с надписью «Образец текста»
  • Далее находится кнопка с надписью «Command»
  • Следующие строки (столько, сколько ViewModelObservableCollection_String элементов) являются текстовыми блоками. Его текст должен быть значением отдельного элемента ViewModelObservableCollection_String .
  • Следующие строки (столько, сколько ViewModelObservableCollection_CustomObject элементов) являются текстовыми полями. Его текст должен быть значением отдельного элемента ViewModelObservableCollection_CustomObject (конкатенация firstString и secondString ).

Как вы можете видеть, содержимое StackPanel представляет собой объединение нескольких коллекций с разными DataTemplate .

Пожалуйста, попросите разъяснений, если что-то недостаточно ясно.

Ответ №1:

  1. Используйте DataTrigger inside ItemTemplate для изменения ControlTemplate Control используемого при сравнении Type . Для этого используйте конвертер, который вернет тип.

    или,

  2. Используйте ContentControl как ItemTemplate .

  3. Определите DataTemplate указание DataType в нем. ContentControl автоматически выберет подходящий DataTemplate для него ContentTemplate .

Второй подход (рекомендуется)

 <Window.Resources>
    <ResourceDictionary>            
        ...
        <DataTemplate DataType="{x:Type sys:String}">
            <TextBlock Background="ForestGreen" Text="{Binding .}"/>
        </DataTemplate>

        <DataTemplate DataType="{x:Type local:CustomObject}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Background="Red" Text="{Binding firstString}"/>
                <TextBlock Background="Red" Text="{Binding secondString}"/>
            </StackPanel>
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>
<ItemsControl>
... 
 <ItemsControl.ItemTemplate>
    <DataTemplate>
        <ContentControl Content="{Binding .}"/>
    </DataTemplate>
 </ItemsControl.ItemTemplate>
 ...
</ItemsControl>
  

Комментарии:

1. Спасибо. Не могли бы вы подробнее рассказать об этом? Я относительно новичок в WPF.

2. Я думаю, ваше второе предложение проще. Не могли бы вы предоставить пример кода? Если нет, пожалуйста, дайте мне какую-нибудь ссылку на это.