繁体   English   中英

WPF/MVVM:如何从 ViewModel 引用视图

[英]WPF/MVVM: How to reference the View from the ViewModel

考虑一个相当经典/简单的 MVVM 构造,其中的项目分别使用 Xaml 绑定到 ViewModel 来显示每个项目。 这些项目是可选择的,并且 ViewModel 有一个IsSelected属性,该PropertyChanged为与设计相关的属性(例如BorderBrush引发PropertyChanged事件,以便 UI 可以正确更新自身。

所需的鼠标交互是通过侦听父容器的隧道和冒泡事件、评估e.OriginalSource.DataContext并最终以一种或另一种方式设置ViewModel.IsSelected来完成的。

这工作正常,如果“设计相关”更改可以由绑定控件单独处理,但我想为每个选定的项目/控件添加一个Adorner ,并使用它来突出显示特定的用户交互,例如选择、移动、调整大小. 这不是问题,如果交互开始并且只影响 ViewModel 绑定的控件之一,因为然后该控件在我的代码范围内是已知的。 但是,如果选择了多个项目(例如,通过“全选”命令),所有受影响的ViewModels的,我怎么访问View /控制,这样我可以创建一个Adorner为每一个可以使用目标控制的视觉效果,位置或尺寸?

我理解 MVVM 原则(或其背后的意图),即 ViewModel 不应依赖于视图,但我没有看到任何其他方式,并且想知道如何最好地实现解决方案。

目前我的方法将包括这样的事情:

public interface IViewModel{
    FrameworkElement Element {get; set;}
}

public partial class MyItemControl : UserControl
{
    public MyItemControl()
    {
        InitializeComponent();

        this.DataContextChanged += OnDataContextChanged;
    }

    private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        (e.NewValue as IViewModel)?.Element = this;
    }
}

有没有另一种方式,例如通过 Xaml 绑定? 通常我不喜欢纯 Xaml 解决方案,但在这种情况下,它会帮助我避免对控件的要求 - 或者我根本不需要使用控件。

并且:这是否确实违反了上述原则?

视图模型永远不应该直接访问视图。 没有例外。 在过去的 15 年里,我开发了一些极具挑战性的 WPF 应用程序,我从来没有遇到过不打破这一基本规则就无法优雅解决的案例。

要回答您的问题,有几种方法可以做到这一点,尽管您选择哪种实现方式取决于您的情况。 最简单的方法之一是使用行为。 您为该行为提供了一些依赖属性,您将这些属性绑定到视图模型中的 INPC 属性,并在那里编写代码以相应地创建/更新您的装饰器。

请记住,行为实际上只是代码隐藏的另一种形式,尽管稍微抽象一些。 许多人陷入使用行为和转换器来实现功能的陷阱,这些功能可以通过 DataTriggers 之类的东西轻松实现。 同样,具体细节将取决于您想要做什么。

暂无
暂无

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

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