MVVM - 视图是否应该引用 Presenter/ViewModel?

发布于 2024-08-05 10:26:20 字数 993 浏览 1 评论 0原文

我一直在研究 PRISM 2 示例,以了解如何最好地处理我正在开发的新应用程序,该应用程序将是 PRISM 2/WPF 应用程序。特别是查看 PRISM 附带的视图注入示例应用程序,我注意到所有视图都实现了一个允许演示者(或 ViewModel)与视图交互的接口。

在过去,我以相反的方式完成了这一点,我将演示者注入到视图中,以便视图可以直接调用演示者上的方法,有点像这样:

    public partial class SomeView : ModuleBase
    {

        private ISomePresenter _somePresenter;

        public SomeView (ISomePresenter somePresenter):this()
        {
            // Give the view a reference to the presenter
            _somePresenter = somePresenter;
            // Bind the View to the presenter
            DataContext = _somePresenter;
        }

    private void btnSubmit_Click(object sender, RoutedEventArgs e)
    {
        // The view can call actions directly on the presenter (OK I should probably use a command for this)
        _somePresenter.SomeAction();
    }
}

上面的技术对我来说似乎足够合理,但是看看样本 我开始质疑这种方法。有没有人对解决这个问题的最佳方法有意见(没有双关语)?

  • 将演示者添加到视图并让视图与演示者交互
  • 将视图添加到演示者并让演示者与视图交互
  • 我还没有想到完全不同的东西?

I've been looking through the PRISM 2 samples for ideas about how to best approach a new application I'm working on, which will be a PRISM 2/WPF app. Looking in particular at the View Injection sample application that ships with PRISM I've noticed that all of the views implement an interface which allows the presenter (or ViewModel) to interact with the View.

In the past I've done this the opposite way round, I inject the presenter into the view so that the view can directly call to methods on the presenter a bit like this:

    public partial class SomeView : ModuleBase
    {

        private ISomePresenter _somePresenter;

        public SomeView (ISomePresenter somePresenter):this()
        {
            // Give the view a reference to the presenter
            _somePresenter = somePresenter;
            // Bind the View to the presenter
            DataContext = _somePresenter;
        }

    private void btnSubmit_Click(object sender, RoutedEventArgs e)
    {
        // The view can call actions directly on the presenter (OK I should probably use a command for this)
        _somePresenter.SomeAction();
    }
}

The technique above seemed reasonable enough to me, but looking at the samples I'm starting to question the approach. Does anyone have views (no pun intended) on the best way to go about this?

  • Add the presenter to the view and get the view to interact with the presenter
  • Add the view to the presenter and get the presenter to interact with the view
  • Something totally different that I haven't thought of yet?

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

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

发布评论

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

评论(2

亚希 2024-08-12 10:26:21

我认为这都是品味问题。就我个人而言,我喜欢您在正在查看的示例中看到的方式。 IView 有一种方法,那就是 SetViewModel(...)。 IViewModel 有一个称为 Object 类型的 View 的属性,它本质上返回 DI 实例化的 IView。

我喜欢这种方式的原因是我几乎总是想先创建一个 ViewModel,并且我希望代码中没有人能够对我的 IView 执行任何操作,除了获取对实例的引用(用于视图注入)或者将视图绑定到 ContentControl),这就是为什么它是对象类型的原因。如果任何代码需要与视图通信,对我来说,它总是通过虚拟机......即使如此,视图通常也会通过绑定进行更新。从 View->ViewModel->UpdateBinding->View 会感觉很奇怪,而不是 VM->UpdateBinding->View

要回答这个问题,我通常不需要引用代码隐藏中的演示者。通常我可以使用绑定到虚拟机的视图中的命令来处理该问题。
在某些情况下,您可能希望保留对演示者的引用来执行示例中的操作,但如果使用正确的工具集,这是可以避免的(由于没有内置命令,SL 变得更困难)。

就像我说的,这完全取决于品味......-

Jer

I think it's all a matter of taste. Personally, I enjoy the way you see it in samples you are looking at. IView has one method, thats SetViewModel(...). IViewModel has a property called View of type Object, that essentially returns the DI instantiated IView.

The reason I like this way is I almost always want to create a ViewModel first and I want nobody in the code to be able to do anything with my IView, except get reference to the instance (for view injection or binding the view to say a ContentControl), which is why its of type object. If any code needs to talk to the View, for me, it's always via the VM...and even then the view gets updated usually via binding. It would feel odd to go from the View->ViewModel->UpdateBinding->View, than it is, VM->UpdateBinding->View

To answer the question, I generally don't need a reference to the presenter in the codebehind. Usually I can handle that with commands from the view being bound to the VM.
In some cases, you might want to keep reference to the presenter to do what you have in your example, but it is avoidable given the correct toolset (makes SL harder that it doesn't have built in commands).

Like I said, it's all a matter of taste...

-Jer

合久必婚 2024-08-12 10:26:20

将 ViewModel 映射到 MVVM 中的视图的最常见方法是使用 DataTemplate :

<DataTemplate DataType="{x:Type vm:SomeViewModel}">
    <v:SomeView />
</DataTemplate>

当您在 ContentControl 或 ItemsControl 中显示 ViewModel 实例时,WPF 将自动为 ViewModel 实例化适当的 View,并且将 View 的 DataContext 设置为 ViewModel 实例。

这样,您就没有对 ViewModel 中的 View 的任何引用,并且 View 仅通过 DataContext 属性引用 ViewModel。如果您确实需要在 View 的代码隐藏中访问 ViewModel,则始终可以强制转换 DataContext (但这意味着 View 了解 ViewModel 的实际类型,从而导致耦合)

The most common approach to map a ViewModel to a View in MVVM is to use a DataTemplate :

<DataTemplate DataType="{x:Type vm:SomeViewModel}">
    <v:SomeView />
</DataTemplate>

When you display a ViewModel instance in a ContentControl or ItemsControl, WPF will automatically instantiate the appropriate View for the ViewModel, and set the View's DataContext to the ViewModel instance.

That way, you don't have any reference to the View in the ViewModel, and the View only references the ViewModel through the DataContext property. In case you really need to access the ViewModel in the View's code-behind, you can always cast the DataContext (but this implies that the View knows about the ViewModel's actual type, which induces coupling)

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