【问题标题】:How to call functions in a main view model from other view models?如何从其他视图模型调用主视图模型中的函数?
【发布时间】:2013-10-31 13:53:58
【问题描述】:

我的程序由地面层的TreeView 和两个contentPresenters 组成。主窗口TreeView 和每个contentPresenter 都有自己的viewModel。

我想从TreeViewViewModel调用mainWindowViewModel中的一个函数。

我需要这样做,因为mainWindowViewModel 控制contentPresenters 中显示的内容,我想手动更新显示。

我猜我会做这样的事情......

TreeViewViewModel:

public class TreeViewViewModel
{
     //Do I need to declare the MainWindowVM?

     public TreeViewViewModel() { ... }

     private void function()
     {
          //Command that affects display

          //Manually call function in MainWindowVM to refresh View
     }
}

我已尝试使用以下方法从TreeViewViewModel 访问MainWindowVM

public MainWindowViewModel ViewModel { get { return DataContext as MainWindowViewModel; } }

但这没有多大意义。因为 MWVM 不是 TreeViewViewModelDataContext

【问题讨论】:

    标签: c# wpf mvvm viewmodel


    【解决方案1】:

    这里使用的delegate 方法和链接的答案可用于任何父子关系和任一方向。这包括从子视图模型到父视图模型、Window 代码后面到子代码后面 Window,甚至是不涉及任何 UI 的纯数据关系。您可以从 MSDN 上的 Delegates (C# Programming Guide) 页面了解有关使用 delegate 对象的更多信息。

    我今天早些时候刚刚回答了一个与此类似的问题。如果您查看Passing parameters between viewmodels 帖子,您会发现答案涉及使用delegate 对象。您可以简单地用您的方法替换这些delegates(来自答案),它会以相同的方式工作。

    如果您有任何问题,请告诉我。


    更新>>>

    是的,对不起,我完全忘记了你想调用方法......我今晚写了太多帖子。所以仍然使用另一篇文章中的示例,只需在 ParameterViewModel_OnParameterChange 处理程序中调用您的方法即可:

    public void ParameterViewModel_OnParameterChange(string parameter)
    {
        // Call your method here
    }
    

    delegate 视为返回父视图模型的路径...就像引发一个名为ReadyForYouToCallMethodNow. 的事件实际上,您甚至不需要输入参数。你可以像这样定义你的delegate

    public delegate void ReadyForUpdate();
    
    public ReadyForUpdate OnReadyForUpdate { get; set; }
    

    然后在父视图模型中(在附加处理程序之后,就像在另一个示例中一样):

    public void ChildViewModel_OnReadyForUpdate()
    {
        // Call your method here
        UpdateDisplay();
    }
    

    由于您有多个子视图模型,您可以在它们都可以访问的另一个类中定义delegate。如果您还有其他问题,请告诉我。


    更新 2 >>>

    再次阅读您的最后一条评论后,我想到了一个更简单的方法,可能实现您想要的……至少,如果我理解正确的话。您可以直接从子视图到父视图模型 Bind。例如,这将允许您将子视图中的 Bind Button.Command 属性转换为父视图模型中的 ICommand 属性:

    TreeViewView:

    <Button Content="Click Me" Command="{Binding DataContext.ParentCommand, 
    RelativeSource={RelativeSource AncestorType={x:Type MainWindow}}}" />
    

    这当然假设有问题的父视图模型的实例被设置为MainWindowDataContext

    【讨论】:

    • 关于这个答案的唯一与我正在做的不同的是 mainWindowViewModel 是父 ViewModel,这是我试图调用的。这对解决方案有何改变?
    • 使用另一篇文章中的示例,您将在 MainWindowViewModel 类中拥有一个 ParameterViewModel_OnParameterChange 处理程序方法。唯一的区别是您在该处理程序中的更新已经在您想要的位置(在父视图模型中),因此您不需要将 parameter 传递给另一个子视图模型......实际上您可以使用相同的示例,但只需对 ParameterViewModel_OnParameterChange 处理程序中的值执行您想要的操作,而不是将其传递给其他视图模型。
    • 这似乎是关于将值传递给其他 ViewModel,并更改参数值。我只想从另一个 ViewModel 中的 Command/Function 调用 mainWindowViewModel 中的函数。我调用的 MWVM 中的函数只是根据所选内容更改 contentPresenter 中显示的内容。
    【解决方案2】:

    最简单的方法是将方法作为Action 传递给子视图模型的构造函数。

    public class ParentViewModel
    {
        ChildViewModel childViewModel;
    
        public ParentViewModel()
        {
            childViewModel = new ChildViewModel(ActionMethod);
        }
    
        private void ActionMethod()
        {
            Console.WriteLine("Parent method executed");
        }
    }
    
    public class ChildViewModel
    {
        private readonly Action parentAction;
    
        public ChildViewModel(Action parentAction)
        {
             this.parentAction = parentAction;
    
             CallParentAction();
        }
    
        public void CallParentAction()
        {
            parentAction.Invoke();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-04
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      相关资源
      最近更新 更多