如何找到ICommand绑定目标(控件)

时间:2011-10-14 01:53:02

标签: wpf mvvm command

我们使用MVVM模式。在View中,我将save命令绑定到一个按钮:

在视图模型中,我想找出save命令绑定目标,是否可能?

    private Button GetBindingControl(ICommand command)
    {
        // What should I do here:

        return button;
    }

2 个答案:

答案 0 :(得分:1)

这是不可能的,它违背了MVVM的目的(无论使用何种控件,都在VM中使用UI逻辑)

也许你可以问一下你要解决的问题。

答案 1 :(得分:1)

正如@Diego所说,这会破坏MVVM的目的,因为我们必须努力不在MVVM的视图模型中包含视觉效果或控件......

说过有两种选择......

  1. 使用RoutedCommands
  2. 使用附加行为。
  3. 在MVVM中不容易使用RoutedCommands,因为它们需要紧密地命令绑定到UI元素,即在我们的例子中是Button。因此他们也打败了MVVM的目的。

    但MVVM很乐意与Attached Behaviors共存。

    许多开发人员回避这个非常强大的功能。我们可以将它与RoutedCommands一起使用。

    在你的情况下

    1. 使用Action委托附加到Button。
    2. 将字符串对象作为命令参数附加。
    3. 在行为中,使用一些Routed命令设置Button.Command。
    4. 在执行的事件处理程序中,从发件人/ originalsource / source获取按钮操作委托作为按钮,然后调用您的Action<>相应地使用e.Parameter字符串值。
    5. 以下示例代码......

      假设您拥有签名Action<Button, string>

      的常用按钮实用程序
      public static class ButtonActionUtilities
      {
          public static Action<Button, string> ButtonActionDelegate
          {
              get
              {
                  return ExecuteButtonClick;
              }
          }
      
          public static void ExecuteButtonClick(Button btn, string param)
          {
              MessageBox.Show(
                "You clicked button " + btn.Content + " with parameter " + param);
          }
      }
      

      然后,附加行为如下......

      public static class ButtonAttachedBehavior
      {
          public static readonly DependencyProperty ActionDelegateProperty
              = DependencyProperty.RegisterAttached(
                  "ActionDelegate",
                  typeof(Action<Button, string>),
                  typeof(ButtonAttachedBehavior),
                  new PropertyMetadata(null, OnActionDelegatePropertyChanged));
      
          public static Action<Button, string> GetActionDelegate(
                                                  DependencyObject depObj)
          {
              return (Action<Button, string>)depObj.GetValue(
                                                  ActionDelegateProperty);
          }
      
          public static void SetActionDelegate(
               DependencyObject depObj, Action<Button, string> value)
          {
              depObj.SetValue(ActionDelegateProperty, value);
          }
      
          private static void OnActionDelegatePropertyChanged(
              DependencyObject depObj,
              DependencyPropertyChangedEventArgs e)
          {
              if (depObj is Button
                  && e.NewValue is Action<Button, string>)
              {               
                  ((Button)depObj).Command
                      = new RoutedCommand(
                              "ActionRoutedCommand",
                               typeof(ButtonAttachedBehavior));
                  ((Button) depObj).CommandBindings.Add(
                      new CommandBinding(
                          ((Button) depObj).Command,
                          OnActionRoutedCommandExecuted));
              }
          }
      
          private static void OnActionRoutedCommandExecuted(
             object sender, ExecutedRoutedEventArgs e)
          {
              var actionDelegate = GetActionDelegate((Button)e.Source);
              actionDelegate((Button) e.Source, (string)e.Parameter);
          }
      }
      

      在XAML上它看起来像这样......

            <StackPanel>
               <Button x:Name="TestButton" Content="Test Me" 
                  local:ButtonAttachedBehavior.ActionDelegate
                      ="{x:Static local:ButtonActionUtilities.ButtonActionDelegate}"
                  CommandParameter
                      ="{Binding Text, ElementName=ParameterTextBox}"/>
      
                <TextBox x:Name="ParameterTextBox"/>
            </StackPanel>
      

      因此,使用上面的代码,您只需将ActionDelegate附加属性设置为approapriate委托,它就会执行该代码。

      我仍然建议您修改现有的代码设置,以区分按钮特定的行为,使其更适合MVVM。