ItemsControl с несколькими шаблонами данных для модели просмотра

Можно ли привязать элемент управления элементами с холстом в качестве шаблона к нескольким шаблонам данных?

У меня есть 2 коллекции, и в зависимости от типа я хотел бы отображать разные элементы управления на своем холсте.

Я не уверен, но я мог бы подумать о Viewmodel, у которого есть 2 ObservableCollections. Например, если бы у меня были «Фигуры» и «связи», и я хотел бы отобразить их обе на холсте? В случае сценария построения диаграмм ...

Я хотел бы сделать это способом mvvm, и я не уверен, что подход с несколькими шаблонами данных верен, но это пришло мне в голову. Но у меня все еще возникают проблемы с закреплением в голове. Если я установил DataContext в ViewModel, мне кажется, что невозможно привязать 2 коллекции к элементу управления элементами ... = (Я также открыт для других идей ....

Это возможно? И если да, то как бы привязка выглядела как


person silverfighter    schedule 29.03.2011    source источник
comment
Вам это нужно ОБЕ для WPF и Silverlight?   -  person Snowbear    schedule 29.03.2011
comment
оба были бы хороши в долгосрочной перспективе ... но сначала WPF было бы здорово ...   -  person silverfighter    schedule 29.03.2011
comment
DataTemplateSelector будет работать как для WPF, так и для Silverlight.   -  person vortexwolf    schedule 29.03.2011


Ответы (4)


Вы можете создать несколько ObservableCollections, а затем привязать свой ItemsSource к CompositeCollection , который присоединяется к этим коллекциям.

Затем в вашем XAML вы можете создать разные DataTemplates для соответствующих типов, используя свойство DataType, которое, как и стили, автоматически применяется, если оно помещается в ресурсы. (Вы также можете создать композит в XAML, который отображается в MSDN, если CollectionContainers должен быть привязан, что немного сложнее хотя)

Пример кода:

ObservableCollection<Employee> data1 = new ObservableCollection<Employee>(new Employee[]
{
    new Employee("Hans", "Programmer"),
    new Employee("Elister", "Programmer"),
    new Employee("Steve", "GUI Designer"),
    new Employee("Stefan", "GUI Designer"),
    new Employee("Joe", "Coffee Getter"),
    new Employee("Julien", "Programmer"),
});
ObservableCollection<Machine> data2 = new ObservableCollection<Machine>(new Machine[]
{
    new Machine("E12", "GreedCorp"),
    new Machine("E11", "GreedCorp"),
    new Machine("F1-MII", "CommerceComp"),
    new Machine("F2-E5", "CommerceComp")
});
CompositeCollection coll = new CompositeCollection();
coll.Add(new CollectionContainer() { Collection = data1 });
coll.Add(new CollectionContainer() { Collection = data2 });
Data = coll;
<ItemsControl ItemsSource="{Binding Data}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:Employee}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}"/>
                <TextBlock Text=" ("/>
                <TextBlock Text="{Binding Occupation}"/>
                <TextBlock Text=")"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Machine}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Model}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Manufacturer}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

Здесь я использую другую панель, но она должна быть такой же для холста.

person H.B.    schedule 29.03.2011
comment
К сожалению, COmpositeCollection недоступен для UWP Framework. - person Luca Lindholm; 28.12.2018
comment
Если класс Employee и Machine наследуются от одного и того же класса X, CompositeCollection не требуется, и достаточно одного ObservableCollection X. - person Viliam; 05.07.2019
comment
@Viliam: Конечно, но это одно важное предположение, которое во многих случаях не выполняется. - person H.B.; 05.07.2019

У вас может быть ObservableCollection<object> в вашей ViewModel и привязать Source ItemsControl к этой коллекции.

Затем, чтобы по-другому взглянуть на разные типы данных, вы можете использовать два DataTemplate без x: Key, но с правильно установленным DataType в ваших ресурсах. ItemsControl затем автоматически выберет соответствующий DataTemplate для вашего элемента.

person Jens    schedule 29.03.2011

Взгляните на селектор шаблонов данных: здесь или здесь.

person TerenceJackson    schedule 29.03.2011

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

person Joel Cochran    schedule 29.03.2011