简体   繁体   English

如何与2个或更多ViewModel进行交互

[英]How to Interact with 2 or More ViewModels

I have written a tool in which a ListBox is bound to a ObserservableCollection<object> with varying datatypes I've define. 我编写了一个工具,其中将ListBox绑定到具有我定义的不同数据类型的ObserservableCollection<object> I use a PropertyDataTemplateSelector to present the data in the ListBox. 我使用PropertyDataTemplateSelector在列表框中显示数据。 The PropertyDataTemplateSelector references several DataTemplates that are set as UserControls . PropertyDataTemplateSelector引用了几个设置为UserControls DataTemplates There is a background class that provides logic to the PropertyDataTemplateSelector by checking the object type and then applying the correct DataTemplate . 有一个后台类,通过检查object类型然后应用正确的DataTemplate来为PropertyDataTemplateSelector提供逻辑。

Here's an abbreviated example of the XAML for the UserControls and the MainWindow . 这是UserControlsMainWindow的XAML的简化示例。

UserControl1 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 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>

Here I set the UserControls to a specified DataTemplate . 在这里,我将UserControls设置为指定的DataTemplate The UserControls were moved out to make the XAML easier to read/navigate. UserControls已移出,以使XAML易于阅读/导航。 In actuality the UserControls are a few hundred lines each. 实际上,每个用户控件都有几百行。

<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>

The ListBox is defined as this. ListBox就是这样定义的。

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

I am using a single ViewModel to drive the MainWindow and the UserControls . 我正在使用一个ViewModel驱动MainWindowUserControls

So that's where I'm at, essentially. 基本上,这就是我的所在。 I have this currently working as I'd like, but in an ongoing effort to learn (this is my first MVVM/WPF/C# project) I'd like to keep exploring how to make my code "better" (however that's defined). 我目前正在按照自己的意愿进行这项工作,但是在不断学习中(这是我的第一个MVVM / WPF / C#项目),我想继续探索如何使我的代码“更好”(无论如何定义) 。 I'm not looking to solve an error here. 我不想在这里解决错误。 So to avoid a general/broad question, I'll ask what I think I want to know. 因此,为了避免一般性/广泛性的问题,我会问我想知道的内容。 Someone can correct me and I'll update the "question(s)" appropriately 有人可以纠正我,我会适当地更新“问题”

Question: How can I go about producing a ViewModel for each of the UserControls ? 问题:如何为每个UserControls生成一个ViewModel Some of the ViewModels , for the UserControls , will occasionally require two-way communication to the MainWindow_ViewModel . 对于UserControls ,某些ViewModels有时会需要与MainWindow_ViewModel进行双向通信。 The main crux of my problem is figuring out how the multiple VMs will communicate. 我问题的主要症结在于弄清楚多个虚拟机如何通信。

You're close, but it's not quite MVVM yet. 您已经接近,但还不 MVVM。 ;) ;)

  1. First, break out all the functionality that is relevant to each UserControl into their own classes. 首先,将与每个UserControl相关的所有功能分解为各自的类。 These are your view-model classes. 这些是您的视图模型类。
  2. Your controls should now become "view" classes, and they deserve their own mark-up file. 您的控件现在应该成为“视图”类,并且它们应该拥有自己的标记文件。 Rather than use a template selector, you can use the DataTemplate.DataType to automatically connect the view-model class type to its view. 您可以使用DataTemplate.DataType自动将视图模型类类型连接到其视图,而不是使用模板选择器。

There are a lot of options for communication between view-models. 视图模型之间的通信有很多选择。 To further your education, I'd consider looking at a light-weight MVVM framework that has built-in solutions for communication. 为了进一步学习,我考虑考虑一种具有内置通信解决方案的轻型MVVM框架。 My personal favorite is Caliburn.Micro , which includes an EventAggregator , a service that provides the ability to publish an object from one view-model to another in a loosely-coupled fashion. 我个人最喜欢的是Caliburn.Micro ,其中包括EventAggregator ,该服务提供了以松散耦合的方式将对象从一个视图模型发布到另一个视图模型的功能。

Keep learning, you're on the right track! 继续学习,您将走上正确的道路!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM