ItemsControl с несколькими DataTemplates для viewmodel

17

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

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

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

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

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

    
задан silverfighter 29.03.2011 в 15:08
источник

4 ответа

38

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

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

    
ответ дан H.B. 29.03.2011 в 15:38
источник
5

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

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

    
ответ дан Jens 29.03.2011 в 15:18
источник
2

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

    
ответ дан TerenceJackson 29.03.2011 в 15:16
источник
-4

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

    
ответ дан Joel Cochran 29.03.2011 в 16:28
источник