在MVVM中调用UserControl的方法

12
我在调用一个UserControl的方法时遇到了问题。请听我说:
  1. 我在SomeView.xaml中有一个名为someControl的UserControl。

  2. SomeView.xaml的DataContext是SomeViewModel.cs。

  3. 我想要在某个地方(位置不限)调用someControl.DoStuff() 方法。

  4. DoStuff方法并非UI特定的(如果它是UI特定的,我可以在SomeView.Xaml.Cs的代码后台直接调用DoStuff方法,但在这种情况下,可能不是UI特定的)。

有什么想法吗?
谢谢!
7个回答

6
您可能不会喜欢这个答案,但是您的ViewModel不应该了解您的UI。如果您在UserControl上有一个非UI方法,则可能放错了位置。
我唯一能想到的是,您可能想要实现某种类型的消息传递(例如MVVM Light中所使用的),以触发执行。
要么这样,要么重新考虑您的代码架构。

1
我理解你的观点,相信我,我已经考虑过这个问题。但是有时你确实需要调用一个方法。例如,用户控件上的方法可能是公开的,并且我可能没有用户控件的源代码,因此无法修改它以适应我的情况。 - LB.
谢谢您的建议,您说得对,ViewModel 不应该知道 View 的存在。 - LB.
也许你可以重新表述问题,说ViewModel试图访问UI实现的Contract。这将使ViewModel不知道UI。 - RockWorld

5

有一个关于如何实现通过解耦ViewModel对View的了解的SO答案,它使用Action委托的方式进行回答。该答案由Mert这里发布。

如果链接不可用,可以在这里查看他的代码。

class MyCodeBehind
{
   public MyCodeBehind()
   {
      Action action = new Action(()=> this.SomeMethodIWantToCall());
      var myVM = new MyVM(action); // This is your ViewModel
      this.DataContext = myVM;
   }

   private void SomeMethodIWantToCall(){...}
}

class MyVM
{
    private Action action;

    public MyVM(Action someAction)
    {
       this.action = someAction;
    }

    private void SomeMethodInVM()
    {
        this.action(); // Calls the method SomeMethodIWantToCall() in your code behind
    }
}

3

从您的需求来看,似乎您希望在VM中发生某些数据或逻辑的情况下执行“DoStuff”,此时最清晰的方法可能是使用由VM触发并由“DoStuff”处理的事件。如果触发器更像状态更改,则还可以将适当的VM数据绑定到UserControl上的新依赖属性,并从DP的更改处理程序调用“DoStuff”。


0
也许你的UserControl应该真正成为一个View,然后应该有一个ViewModel,其中包含DoStuff()方法。SomeViewModel将已实例化(或至少导致实例化)SomeControlViewModel,因此能够调用其上的方法。

0
如果您采用视图优先的方法(并且您的 VM 在 XAML 中实例化为资源),则可以使用一些普通事件将控件的 DoStuff 方法与 VM 上的某个事件连接起来(例如 Loaded 事件)。

0
如果DoStuff()方法执行一些UI特定的逻辑,则该方法位于正确的位置。否则,它应该位于另一个对象中(例如SomeViewModel)。
当通过接口分离时,SomeViewModel可以调用SomeView上的方法。如何实现这一点可以参考WPF Application Framework (WAF)

-1
在MVVM设计中,通常的想法是不要在您的UserControl(即xaml.cs文件)中放置任何代码(在理想的情况下)。 UI和ViewModel之间的所有交互都应通过命令和绑定处理...那么为什么您需要在用户控件中使用DoStuff呢?
您可能会有类似以下的内容:
<Button Command="{Binding myCommandOnTheDataContextViewModel}" Content="{Binding somePropertyOnTheViewModel}" />

"MVVM设计的思想通常是在您的UserControl中不要有任何代码。" 您能展示一下MVVM的创始人的引用吗? 然而,我并没有看到这一点。如果您有纯粹与视图相关的代码/逻辑,为什么不将其放在代码后面呢?虽然这种情况非常罕见,但如果必要的话,为什么不呢? - alzaimar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接