如何在 WPF MVVM 类似资源管理器的应用程序中实现依赖于当前选择的菜单项

发布于 2024-08-26 08:05:03 字数 928 浏览 6 评论 0原文

我是 WPF 和 MVVM 的新手,我正在开发一个利用两者的应用程序。该应用程序类似于 Windows 资源管理器,因此请考虑一个具有带菜单 (ShellViewModel)、树控件 (TreeViewModel) 和列表控件 (ListViewModel) 的主窗口的应用程序。我想实现编辑->等菜单项删除,删除当前选定的项目(可能位于树中或列表中)。

我正在使用 Josh Smith 的 RelayCommand,并且将 menuitem 绑定到 ShellViewModel 中的 DeleteItemCommand 很容易。然而,实现 DeleteItemCommand 似乎需要 ShellViewModel 和两个子视图模型(TreeViewModel 和 ListViewModel)之间进行一些相当紧密的耦合,以跟踪焦点/选择并将操作定向到正确的子视图以进行实现。这对我来说似乎是错误的,让我觉得我错过了一些东西。

编写焦点管理器和/或选择管理器来进行簿记似乎并不太难,并且可以在不将类耦合在一起的情况下完成。窗口系统已经在跟踪哪个视图具有焦点,而且看起来我会重复代码。

我不确定如何将命令从 ShellViewModel 路由到 ListViewModel 或 TreeViewModel 以完成实际工作而不弄乱代码。有一天,应用程序将扩展到包括两个以上的孩子,我希望 shell 尽可能不了解孩子,以使扩展尽可能轻松。

查看一些示例 WPF/MVVM 应用程序(Karl Shifflett 的 CipherText、Josh Smith 的 MVVM 演示< /a> 等),我还没有看到任何执行此操作的代码(或者我不理解它)。

无论您是否认为我的方法偏离了基础,或者我只是错过了一些细微差别,请分享您的想法并帮助我回到正轨。谢谢!

I am new to WPF and MVVM, and I am working on an application utilizing both. The application is similar to windows explorer, so consider an app with a main window with menu (ShellViewModel), a tree control (TreeViewModel), and a list control (ListViewModel). I want to implement menu items such as Edit -> Delete, which deletes the currently selected item (which may be in the tree or in the list).

I am using Josh Smith's RelayCommand, and binding the menuitem to a DeleteItemCommand in the ShellViewModel is easy. It seems like implementing the DeleteItemCommand, however, requires some fairly tight coupling between the ShellViewModel and the two child view models (TreeViewModel and ListViewModel) to keep track of the focus/selection and direct the action to the proper child for implementation. That seems wrong to me, and makes me think I'm missing something.

Writing a focus manager and/or selection manager to do the bookkeeping does not seem too hard, and could be done without coupling the classes together. The windowing system is already keeping track of which view has the focus, and it seems like I'd be duplicating code.

What I'm not sure about is how I would route the command from the ShellViewModel down to either the ListViewModel or the TreeViewModel to do the actual work without making a mess of the code. Some day, the application will be extended to include more than two children, and I want the shell to be as ignorant of the children as possible to make that extension as painless as possible.

Looking at some sample WPF/MVVM applications (Karl Shifflett's CipherText, Josh Smith's MVVM Demo, etc.), I haven't seen any code that does this (or I didn't understand it).

Regardless of whether you think my approach is way off base or I'm just missing a small nuance, please share your thoughts and help me get back on track. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

世俗缘 2024-09-02 08:05:03

Josh Smith 的 MVVM 实现存在一些固有的问题。看看 Ward Bell 关于该主题的帖子:http:// /neverindoubtnet.blogspot.com/2010/03/mvvm-josh-smiths-way.html。您可能想看看一些替代的 MVVM 框架,例如 Caliburn,它采用 ViewModel 优先方法并打破这种耦合。

There are some inherent issues with Josh Smith's implementation of MVVM. Take a look at Ward Bell's post on the subject: http://neverindoubtnet.blogspot.com/2010/03/mvvm-josh-smiths-way.html. You may want to take a look at some alternative MVVM frameworks such as Caliburn that take a ViewModel first approach and break this coupling.

夏了南城 2024-09-02 08:05:03

RelayCommand 只是在 ViewModel 中获取可绑定到 View 的命令的一种方法。

我想我会倾向于放弃所有不同的 MVVM 架构变体和示例应用程序,而只使用良好的旧 OOD。为什么不为 TreeViewVm 和 ListViewVm 提供某种 ViewModel 基类(即,DetailsViewModelBase)。将DeleteCommand 与CanDelete 和Delete 方法放在其中,这些方法具有与子类共享的尽可能多的实现(如果没有,则为抽象),还有一个SelectedItem。然后将 SelectedItem 绑定到类似于下面的 xaml 的控件:

    <ListView AlternationCount="2" MinHeight="250" MaxHeight="400" 
          ItemsSource="{Binding Projects.View}" 
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedProject, Mode=TwoWay}"
          behaviors:SelectionBehavior.DoubleClickCommand="{Binding PickCommand}"
          ItemContainerStyle="{StaticResource listingRowStyle}"
                      >

键绑定是 SelectedItem 和 IsSynchronizedWithCurrentItem。

HTH,
贝里尔

The RelayCommand is just a way to get a command in your ViewModel that can be bound to your View.

I think I would be inclined to step back from all of the different MVVM architectural variations and sample apps, and just use good old OOD. Why not have a ViewModel base class of some sort (ie, DetailsViewModelBase) for TreeViewVm and ListViewVm. Put a DeleteCommand in there with CanDelete and Delete methods that have as much implementation as the subclasses share (or abstract if none), and a SelectedItem as well. Then bind the SelectedItem to the controls similar to the xaml below:

    <ListView AlternationCount="2" MinHeight="250" MaxHeight="400" 
          ItemsSource="{Binding Projects.View}" 
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedProject, Mode=TwoWay}"
          behaviors:SelectionBehavior.DoubleClickCommand="{Binding PickCommand}"
          ItemContainerStyle="{StaticResource listingRowStyle}"
                      >

The key bindings being SelectedItem and IsSynchronizedWithCurrentItem.

HTH,
Berryl

看轻我的陪伴 2024-09-02 08:05:03

我发现 Kent Boogaart 的一篇 博客文章 描述了他的内容调用 ActiveAwareCommand。尽管我还没有尝试过,但这似乎符合我的要求。该帖子的评论提到 Prism 的 IActiveAware 具有类似的行为。

I found a blog post by Kent Boogaart that describes what he calls an ActiveAwareCommand. This seems to do what I was looking for, although I haven't yet tried it. A comment on the post mentions Prism's IActiveAware as having similar behavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文