gpt4 book ai didi

wpf - M-V-VM - 在 ViewModel 中使用命令的任何示例?

转载 作者:行者123 更新时间:2023-12-03 15:02:45 25 4
gpt4 key购买 nike

我一直在使用我的 M-V-VM 风格开发一个非常大的 LOB 应用程序,我称之为 M-V-MC(Model-View-ModelController),它是 M-V-C 和 M-V-VM 之间的一种组合。我已发布 this answer关于 View 如何在 M-V-VM 中实例化到问题“what-are-the-most-common-mistakes-made-in-wpf-development”。

Sam对我的回答发表了以下评论:

This creates a follow-up-question: how do you create the views? I use RelayCommands to bind actions from the view to the ViewModel, so the view does not even know an action has fired, does not know he should open a new view. Solution: create an event in the VM for the View to subscribe to?



当我最初开始 M-V-VM 开发时,我认为一切都应该存在于 ViewModel 中,并且研究了很多来自像 Josh Smith 这样的人的例子。和 Karl Shifflett .但是,我还没有想出一个很好的例子来说明命令何时需要存在于 ViewModel 中。

例如,假设我有一个显示客户的 ListView,以及一个单击以允许我编辑当前选择的客户的按钮。 ListView (View) 绑定(bind)到 CustomerVM (ViewModel)。单击该按钮会触发 EditCustomerCommand,它会打开一个弹出窗口,允许我编辑 CustomerVM 的所有属性。这个 EditCustomerCommand 在哪里?如果它涉及打开一个窗口(UI 功能),它不应该在 View 的代码隐藏中定义吗?
alt text

有没有人有任何我应该在 View 和 ViewModel 中定义命令的示例?

Matthew Wright状态如下:

New and delete from a list would be good examples. In those cases, a blank record is added or the current record is deleted by the ViewModel. Any action taken by the view should be in response to those events occurring.



所以如果我点击新按钮,会发生什么? CustomerVM 的新实例由 Parent ViewModel 创建并添加到它的集合中,对吗?那么如何打开我的编辑屏幕呢? View 应该创建 Customer ViewModel 的新实例,并将其传递给 ParentVM.Add(newlyCreatedVM) 方法,对吗?

假设我通过虚拟机上的 DeleteCommand 删除客户记录。 VM 调用业务层并尝试删除记录。它不能,所以它会向虚拟机返回一条消息。我想在对话框中显示此消息。 View 如何从命令操作中获取消息?

最佳答案

从来没有想过我会看到自己在一个问题中被引用。

我自己思考了一段时间这个问题,并为我的代码库做出了一个相当务实的决定:

在我的代码库中,ViewModel 在 Action 发生时被调用,我希望它保持这种状态。此外,我不希望 ViewModel 控制 View 。

我做了什么?
我添加了一个导航 Controller :

public interface INavigation
{
void NewContent(ViewModel viewmodel);
void NewWindow(ViewModel viewmodel);
}

这个 Controller 确实包含两个 Action :NewContent() 确实在当前窗口中显示新内容,NewWindow() 创建一个新窗口,用内容填充它并显示它。
当然,我的 View 模型不知道要显示哪个 View 。但是他们确实知道要显示哪个 View 模型,因此根据您的示例,当执行 DeleteCommand 时,它将调用导航服务函数 NewWindow(new ValidateCustomerDeletedViewModel()) 以显示一个窗口,说明“客户已被删除”(对于这个简单的消息框,但很容易为简单的消息框提供一个特殊的导航器功能)。

viewmodel如何获取导航服务?

我的 viewmodel 类有一个导航 Controller 的属性:
public class ViewModel
{
public INavigation Navigator { get; set; }
[...]
}

当 View 模型附加到窗口(或任何显示 View )时,窗口将设置 Navigator 属性,因此 View 模型可以调用它。

导航器如何创建 View 模型的 View ?

您可以有一个简单的列表来为哪个 View 模型创建哪个 View ,在我的情况下,我可以使用简单的反射,因为名称是匹配的:
public static FrameworkElement CreateView(ViewModel viewmodel)
{
Type vmt = viewmodel.GetType();
// big bad dirty hack to get the name of the view, but it works *cough*
Type vt = Type.GetType(vmt.AssemblyQualifiedName.Replace("ViewModel, ", "View, "));
return (FrameworkElement)Activator.CreateInstance(vt, viewmodel);
}

当然, View 需要一个接受 View 模型作为参数的构造函数:
public partial class ValidateCustomerDeletedView : UserControl
{
public ValidateCustomerDeletedView(ValidateCustomerDeletedViewModel dac)
{
InitializeComponent();
this.DataContext = dac;
}
}

我的 window 看起来怎么样?

很简单:我的主窗口确实实现了 INavigation 界面,并在创建时显示了一个起始页。你自己看:
public partial class MainWindow : Window, INavigation
{
public MainWindow()
{
InitializeComponent();
NewContent(new StartPageViewModel());
}

public MainWindow(ViewModel newcontrol)
{
InitializeComponent();
NewContent(newcontrol);
}

#region INavigation Member
public void NewContent(ViewModel newviewmodel)
{
newviewmodel.Navigator = this;
FrameworkElement ui = App.CreateView(newviewmodel);
this.Content = ui;
this.DataContext = ui.DataContext;
}

public void NewWindow(ViewModel viewModel)
{
MainWindow newwindow = new MainWindow(viewModel);
newwindow.Show();
}
#endregion
}

(这同样适用于 NavigationWindow 并将 View 包装到页面中)

当然这是可测试的,因为导航 Controller 可以很容易地模拟。

我不确定这是否是一个完美的解决方案,但它现在对我来说效果很好。欢迎任何想法和意见!

关于wpf - M-V-VM - 在 ViewModel 中使用命令的任何示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/424927/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com