【问题标题】:Bind a Parent window's event to UserControl inner handlers with MVVM使用 MVVM 将父窗口的事件绑定到 UserControl 内部处理程序
【发布时间】:2011-07-07 23:30:46
【问题描述】:

我有一个在 ContentControl 中加载用户控件的父窗口。父窗口有一个带有一些按钮的工具栏(即保存按钮)。我想分配将在用户控件内处理的那些按钮命令。

我需要从用户控件的 ViewModel 管理我自己的 ICommand 命令,因此总结一下:用户单击“保存”按钮(在主窗口上),因此该按钮会触发用户控件处理的事件以保存其中的信息控件。

这可能吗?

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    有两种方法。

    1. 使用 MVVM,
      由于您的窗口包含 UserControl,因此您需要进行设置,以便 Window 具有对 UserControl ViewModel 的引用(假设它被称为 UserControlViewModel)。如果您在 UserControlViewModel 中有一个命令,则可以通过调用以下命令绑定到该命令: UserControlViewModel.Command 类似:

      <Button x:Name="Save" Content="Save" Command="{Binding UserControlViewModel.SaveCommand}">
      
    2. 使用事件处理程序

      同样,您的窗口需要有对实现事件处理程序的类的引用。您可以在 Window XAML 文件中包含以下内容:

          <Button x:Name="Save" Content="Save" Clicked="SaveButtonClicked"/>
      

      然后在你的代码后面,

               private void SaveButtonClicked( .... sender, .... e)
                {
                     UserControlClass.SaveData();
                      // or using command
                     UserControlClass.MyCommand.Execute()
                 }
      

    【讨论】:

    • 嗨@seekle,如果我没有明确声明用户控件,而是使用带有viewModel 的ContentControl 加载它们怎么办。我如何告诉通用父级“知道”“某些”viewModel 正在监听它的事件?谢谢
    【解决方案2】:

    好的,您正在尝试将子元素的命令绑定到父窗口。首先为用户控件命名(例如 x:Name = MyUserControl)并在用户控件的 datacontext/viewmodel 中编写公共命令(例如 ICommand MyCommand)。现在在按钮中执行此操作

    <Button x:Name="SaveButton" Command={Binding ElementName=MyUserControl, Path=DataContext.MyCommand} />
    

    这会将保存按钮命令绑定到子用户控件的数据上下文中的命令:)

    顺便说一句,如果您正在寻找其他方式(即将子命令绑定到 mvvm 中的父级),您将需要使用 FindAncestor。你可以看看我的codeproject article 关于这个:)

    【讨论】:

    • 感谢@Amit 提供代码和链接。我想要做的是有一个带有一些按钮的包装器,我将加载我想要的任何用户控件,但是每个用户控件都应该响应单击我的包装器的事件。我可以用更通用的方式来做吗?或者,我这样做错了吗?
    • @Rodrigo Caballero:我能想到的最好方法是CompositeCommand。你可以下载Prism doc看第6章。这会给你一个思路,然后你可以下载Prism的代码并用你自己的方式实现:)
    【解决方案3】:

    这听起来像是路由命令可以工作的情况。对于路由命令,将收费栏按钮的命令设置为“保存”。然后在用户控件中,添加一个监听“保存”命令的命令绑定。

    <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <UserControl.CommandBindings>
        <CommandBinding 
          Command="Save" 
          CanExecute="SaveCommand_CanExecute" 
          Executed="SaveCommand_Executed" 
        />
      </UserControl.CommandBindings>
    
    </UserControl>
    

    在命令绑定的代码隐藏事件处理程序中,只需找到视图模型并在其视图模型上调用保存命令。如果你想要更纯粹的 MVVM 方法,你可以试试Josh Smith's approach to routed commands with MVVM

    使用这种方法,只要用户控件在其中某处有焦点,那么保存按钮的保存命令将路由到用户控件的命令绑定并执行保存命令。

    我认为这可能会实现您将工具栏按钮与 ContentPresenter 中动态加载的用户控件分离的目标。

    【讨论】:

    • 确实,这种方法可以解决它。但是,您正在谈论使用 ApplicationCommands。如果我想使用自己的 ICommands(在特定的 ViewModel 上)怎么办,我认为这是不可能的,也许将命令作为静态属性,但我认为可能还有另一种方法。
    • 这种方法确实使用 ApplicationCommands,您可以在 UserControl 中截获它。一旦被拦截,就可以在代码中调用自己的ICommand。或者,您可以使用类似 Josh Smith 的方法将截获的应用命令直接传递给 VM。
    【解决方案4】:

    过了一会儿,我回到这个问题。我需要与我的父窗口进行通信,所以我决定直接从父窗口执行 view-viewmodel 数据上下文绑定,主要是因为我希望子视图模型附加到从其父窗口触发的事件,并且我可以向父窗口触发事件为了显示子控件之外的消息。

    我知道我可能没有完全使用 MVVM 模式,但我想更好地控制这些功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-03
      • 2018-02-15
      • 2011-04-10
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      相关资源
      最近更新 更多