使用Microsoft(或其他)功能区与大型项目和MVVM

spl*_*tor 8 wpf ribbon mvvm

我们的应用程序是一个包含许多模块和视图的大型项目 主窗口中有一个功能区,我们正在寻找将功能区集成到应用程序中的最佳方法.

我创建了一个服务模块,视图可以注册以添加与它们相关的功能区项目,此外,任何主视图实例都可以提供与该实例相关的自己的功能区项目.一个RibbonItem是一个小类,它抽象一个功能区项的选项,主要有Title,Description,Command,UIType和ChildItems.当主视图发生变化时,该服务负责重建功能区.

我的一位同事认为这是糟糕的MVVM,因为用户需要用C#代码而不是XAML来设计他们的功能区视图,他还说这样做很难让一组项目一次被禁用或启用,如这些项目的每个命令都需要单独更新其CanExecute.相反,他建议使用主要的Ribbon View和ViewModel文件,其中每个想要为其模块或视图添加功能区按钮的开发人员需要在View XAML中添加它们,并在ViewModel中添加相关命令.此外,VisualStates将用于根据ViewModel中的更改(例如视图更改或选择更改)确定要显示或启用的项目.我真的不喜欢这个解决方案,主要是因为所有开发人员都必须将他们的模块知识放在一次大文件中.

请注意,功能区中的某些项目(例如,选项,退出)对整个应用程序是通用的,而某些项目与特定应用程序域相关,而某些项目仅与特定视图相关.

编辑:我想我的主要问题是允许多个开发团队集成在一个功能区上的推荐方法是什么?我们是否应该有一个RibbonView和一个RibbonViewModel,它将包含功能区中的所有可能项目,每个团队都会将其项目添加到这些V/VM,并定义何时显示它们的逻辑(可能通过使用可视状态) ?或者我们是否允许每个视图,视图模型或模块在服务中注册功能区项目(在他们自己的C#代码中),然后让服务在活动视图随注册到该类型的所有项目更改时根据需要呈现功能区?或者有没有更好的方法来实现这种集成?

你怎么看?您是否对如何管理多个开发人员常见的单一功能区资源有更好的想法或意见?

谢谢,splintor

Jos*_*ose 1

我同意威尔的评论,你的视图模型不应该关心或知道它是如何渲染的,或者设计师是否决定改变它的渲染方式。

ViewModel应该只包含表示层渲染它所需的所有信息。

因此,ViewModel 应该具有功能区栏需要绑定才能运行的所有属性。然后您可以使用 Resources.xaml 或其他一些策略来呈现它。

在黑暗中拍摄,我会为 ViewModel 尝试这样的操作:

public interface IMenuViewModel : INotifyPropertyChanged
{
  ICommand Command {get;}
  string Title {get;}
  string Description {get;}
  UIType Type {get;}
  IList<IMenuViewModel> ChildItems {get;}
}
Run Code Online (Sandbox Code Playgroud)

然后,我可能会创建一个抽象类,它提供INotifyPropertyChanged带有集合类的实现,该实现INotifyCollectionChanged来处理管道代码。

然后我可能会在 Resources.xaml 中做类似的事情

<DataTemplate DataType="{x:Type vm:IMenuViewModel}">
  <StackPanel>
    <Button Command="{Binding Command}" Content="{Binding Type}"/>
    <ItemsControl ItemsSource="{Binding ChildItems}"/>
  </StackPanel>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

为您的视图模型提供默认视图

然后有人需要做的就是在您的功能区栏中创建一个条目

1)实现IMenuViewModel

2) 如果他们希望其小部件以不同方式呈现,则可以选择将另一个 DataTemplate 条目添加到 resources.xaml 中,如下所示:

<DataTemplate DataType="{x:Type vm:FooViewModel}">
    <v:FooView />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

我希望我没有深入研究如何实施。

要点是 aViewModel应该只公开视图完成其工作(渲染ViewModel)所需的属性,而不是公开视图ViewModel完成工作或关心它是如何完成的。