ItemsControl с несколькими шаблонами данных для модели представления - PullRequest
22 голосов
/ 29 марта 2011

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

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

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

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

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

Ответы [ 4 ]

50 голосов
/ 29 марта 2011

Вы можете создать несколько 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>

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

6 голосов
/ 29 марта 2011

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

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

2 голосов
/ 29 марта 2011

Посмотрите на селектор шаблона данных: здесь или здесь .

0 голосов
/ 29 марта 2011

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

...