2013-12-03 3 views
0

Я написал инструмент, в котором ListBox привязан к ObserservableCollection<object> с различными типами данных, которые я определил. Я использую PropertyDataTemplateSelector для представления данных в ListBox. PropertyDataTemplateSelector ссылается на несколько DataTemplates, которые установлены как UserControls. Существует класс фона, который обеспечивает логику для PropertyDataTemplateSelector, проверяя тип object, а затем применяя правильный DataTemplate.Как взаимодействовать с 2 или более ViewModels

Вот сокращенный пример XAML для UserControls и MainWindow.

UserControl1

<TextBlock Text="{Binding Path=Val1}" 
       Style="{StaticResourse Yes}" /> 

    <Button Content="I'm Button 1" 
      Command="{Binding Path=PathtoCommand1}" 
      CommandParameter="{Binding Parameter1}" 
      IsEnabled="{Binding IsEnabled1}" /> 

    <Button Content="I'm Button 2" 
      Command="{Binding Path=PathtoCommand2}" 
      CommandParameter="{Binding Parameter2}" 
      IsEnabled="{Binding IsEnabled2}" 
      Tag="{Binding Path="DataContext.TagItem2}"> 

     <Button.ContextMenu> 
     <ContextMenu> 
      <MenuItem IsCheckable="True" 
        IsChecked="{Binding Path=Tag}" 
        DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" /> 
     </ContextMenu> 
     </Button.ContextMenu> 

    </Button> 
    </StackPanel> 
</UserControl> 

UserControlN

<UserControl x:Class="AwesomerControl"> 
    <StackPanel Orientation="Vertical"> 

    <TextBlock Text="{Binding Path=FancyName2}" 
       Style="{StaticResourse Yes}" /> 

    <Button Content="Clicker 1" 
      Command="{Binding Path=DoSomethingGreat1}" 
      CommandParameter="{Binding Greatness1}" 
      IsEnabled="{Binding IsTurnedOn1}" /> 

    <Button Content="Clicker 2" 
      Command="{Binding Path=DoSomethingGreat2}" 
      CommandParameter="{Binding Greaterness2}" 
      IsEnabled="{Binding IsTurnedOn2}" 
      Tag="{Binding Path="DataContext.TagItem2}"> 

     <Button.ContextMenu> 
     <ContextMenu> 
      <MenuItem IsCheckable="True" 
        IsChecked="{Binding Path=Tag}" 
        DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" /> 
     </ContextMenu> 
     </Button.ContextMenu> 

    </Button> 
    </StackPanel> 
</UserControl> 

Здесь я установил UserControls к указанному DataTemplate. UserControls были перемещены, чтобы упростить чтение/перемещение XAML. На самом деле UserControls составляет несколько сотен строк.

<Window.Resources> 
    <DataTemplate x:Key"Template1"> 
    <customControls:AwesomeControl/> 
    </DataTemplate> 
    ... 
    <DataTemplate x:Key"TemplateN"> 
    <customControls:AwesomerControl/> 
    </DataTemplate> 


    <dts:PropertyDataTemplateSelector x:Key="templateselector" 
            Template1="{StaticResource Template1"} 
            ... 
            TemplateN="{StaticResource TemplateN"} 
</Window.Resources> 

ListBox определяется как это.

<ListBox ItemSource="{Binding Path=CollectionofMyObjects}" 
     ItemTemplateSelector="{StaticResource templateselector}" /> 

Я использую один ViewModel для привода MainWindow и UserControls.

Так вот, где я нахожусь, по существу. У меня есть эта работа в настоящее время, как хотелось бы, но в постоянной попытке узнать (это мой первый проект MVVM/WPF/C#), я хотел бы продолжить изучение того, как сделать мой код «лучше» (однако это определено) , Я не собираюсь решать проблему здесь. Поэтому, чтобы избежать общего/широкого вопроса, я спрошу, что я думаю, что хочу знать. Кто-то может исправить меня, и я буду обновлять «вопрос (ы)» соответственно

Вопрос: Как я могу идти о производстве ViewModel для каждого из UserControls? Некоторые из ViewModels, для UserControls, будут иногда требовать двухсторонней связи с MainWindow_ViewModel. Основной проблемой моей проблемы является выяснение того, как будут взаимодействовать несколько виртуальных машин.

ответ

1

Вы близко, но это не довольно MVVM еще нет. ;)

  1. Во-первых, выделите все функциональные возможности, относящиеся к каждому UserControl, в свои классы. Это ваши классы модели представлений.
  2. Теперь ваши элементы управления должны стать классами «просмотра», и они заслуживают своего собственного файла разметки. Вместо использования селектора шаблонов вы можете использовать DataTemplate.DataType, чтобы автоматически подключить тип класса модели просмотра к его виду.

Существует множество вариантов взаимодействия между моделями просмотра. Чтобы продолжить ваше образование, я бы подумал о том, чтобы взглянуть на легковесную структуру MVVM, в которой есть встроенные решения для общения. Мой личный фаворит - Caliburn.Micro, который включает в себя EventAggregator, услугу, которая предоставляет возможность публиковать объект с одной модели представления на другую по-слабому.

Продолжайте учиться, вы на правильном пути!

+0

Действительно ли это не 'MVVM'? Из того, что я читаю, он делает это правильно. Вы можете это уточнить? Но вы правы, что модульность может быть определенно улучшена. – DHN

+0

Я сделал быстрое редактирование, чтобы убедиться, что мы говорим одно и то же. Каждый из моих UserControls определяется как отдельное представление. Это модульность, о которой вы говорили? Правильно ли я полагаю, что когда вы говорите, что класс «вид» заслуживает собственных файлов разметки, вы имеете в виду отдельную модель представления (а не код, стоящий за ними) для этих файлов? – StinkerPeter

+0

MVVM должен использовать несколько видов, а также модели просмотра. Если у вас есть только 1 файл модели представления и 1 вид (XAML), то он должен, разумеется, не использовать все преимущества шаблона. :) И Питер, я имею в виду, что каждый из этих UserControls должен быть определен в собственном .xaml-файле (желательно в папке «Views»). – Charlie

Смежные вопросы