【问题标题】:How can i access a control in mvvm model in viewmodel?如何在 viewmodel 中访问 mvvm 模型中的控件?
【发布时间】:2012-12-23 13:25:40
【问题描述】:

我有一个 WPF 窗口,在那个窗口中我有一个网格。

我使用 M-V-VM 模型,我想在代码中(在视图模型中)动态地将 TextBox 添加到网格中

如何访问网格?

【问题讨论】:

  • 在走这条路之前,我会确保它是绝对必要的,除非绝对没有其他选择,否则从视图模型访问视图通常是不好的做法。
  • @BenjaminPaul 所说的。使用 MVVM 时,您无需从 ViewModel 添加控件。使用绑定来完成这项工作。
  • 是的,我知道,这正是我的意思。然而,我有时需要在视图模型中获得对控件的引用,以适应不支持常规绑定的控件。这也是我所指的场景。

标签: c# wpf silverlight mvvm devforce


【解决方案1】:

使用 Supervising Controller 模式。

阅读:

CaliburnMicro MVVM 框架的示例实现如下所示(对所有其他框架都一样——或者如果你自己做 MVVM,你也可以手动做):

http://drc.ideablade.com/devforce-2012/bin/view/Documentation/cocktail-tutorial-talk-to-view

示例:

1) 定义接口IView,其中ViewModel (VM) 将使用所需的方法与View 对话

public interface IView 
{
    void AddTextBoxToGrid();
}

2) 从你的IView继承View后面的代码并实现IView.AddTextboxToGrid()方法

public partial class View: IView 
{
    public void AddTextBoxToGrid() 
    {  
        // implement here your custom view logic using standard code behind; 
    }
}

3) IView 类型的属性添加到您的VM

public class ViewModel 
{
    public IView View { get; set; }
}

4) VM 上的View 属性设置为View 的实例IView 例如在后面的代码中:

 DataContext.View = this as IView; 

或者在 Caliburn 中你可以使用 IScreen.OnViewAttached 覆盖方法)

public partial class View: IView 
{
    public View()
    {
        // access you VM by the strategy of your framework or choice - this example is when you store your VM in View's DataContext
        (DataContext as ViewModel).View = this as IView;
    } 

    public void AddTextBoxToGrid() 
    {  
        // implement here your custom view logic using standard code behind; 
    }
}

5) 在您的VM 致电IView.AddTextboxToGrid()

public class ViewModel 
{
    public IView View { get; set; }

    public void AddTextBoxToGrid() 
    {
        if (View == null) return;
        View.AddTextBoxToGrid()
    }
}

【讨论】:

  • 最好使用构造函数注入将IVew实例发送到ViewModel(我的意思是,ViewModel类的构造函数应该接受IView实例)。
  • 需要强调的是,在视图中从 viewmodel 创建依赖也不是最纯粹的 mvvm。当您使用(DataContext as SomeViewModel) 时,您的视图将依赖于SomeViewModel,这可能是不可取的。你怎么看?
  • @MohammadDehghan:您将如何使用 Caliburn 实现这一点?
  • 非常明确的答案。在保持 MVVM 模式的同时还有其他选择吗?
  • @heltonbiker 为什么不受欢迎?视图总是知道视图模型(请记住,所有绑定都引用视图模型的属性)并且添加一个直接依赖项不会以任何其他方式造成伤害。什么是“禁止”是视图模型直接知道视图。
【解决方案2】:

您应该将创建代码移至 View,并且 ViewModel 应该在应该调用它时通知视图。

【讨论】:

    【解决方案3】:

    您还可以在视图后面的代码中使用视图的 DataContext(即 ViewModel),并将文本框添加到那里的网格中。那会更有意义。

    如果您在 XAML 文件中为网格命名,您将能够立即在后面的代码中访问网格。

    【讨论】:

      【解决方案4】:

      如果您使用的是 Caliburn Micro,请执行以下步骤:

      1. 使ViewModel继承自接口IViewAware;你要实现这个接口的两个方法AttachView和GetView。

      2. 定义一个 View 类型的变量来获取对 View 的引用

      3. 详见下文:

        private SomeViewClass v;
        public void AttachView(object view, object context = null)
        {
            v = view as BomView;
            if (ViewAttached != null)
                 ViewAttached(this,
                 new ViewAttachedEventArgs() { Context = context, View = view });
        }
        
        public object GetView(object context = null)
        {
            return v;
        }
        

      稍后您可以通过 v 访问视图上的单个元素,例如 v.txtName="John";等等……

      【讨论】:

      • BomView = SomeViewClass。视图类的名称。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      相关资源
      最近更新 更多