是否可以将命令绑定到资源?

时间:2013-07-26 12:28:17

标签: c# wpf mvvm

我有一个提供RelayCommand LoadImage的视图模型。

通常我会使用一个按钮并将命令绑​​定到此按钮。

但是我想从视图的代码隐藏中调用LoadImage命令(我需要做一些不能放入视图模型的视图相关内容)

我知道的一种方法是为按钮创建一个事件处理程序,例如Button_Click。 在Button_Click中,我将DataContext转换为相应的ViewModel,并使用此实例调用(DataContext as MyViewModel).LoadImage.Execute(...)

这很奇怪,因为我需要知道视图模型。

我正在尝试的是将LoadImage绑定到按钮而不是绑定到视图中的资源,因此Button_Click事件只需要调用具有给定名称的FindResource并将其强制转换为ICommand,而无需知道特定的ViewModel

这可能吗?命令本身不是静态的,因为它需要知道它所调用的上下文。

2 个答案:

答案 0 :(得分:1)

您可以通过创建行为来实现,这需要在项目中引用Prism:

public class LoadImageBehavior : Behavior<Button>
{
    public public static static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof (ICommand), typeof (LoadImageBehavior));

    public ICommand Command
    {
        get { return (ICommand) GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.Click += AssociatedObject_Click;
    }

    private void AssociatedObject_Click(object sender, RoutedEventArgs e)
    {
        //Logic...

        if(Command != null && Command.CanExecute(null))
            Command.Execute(null);

        //Logic...
    }
}

在Xaml:

    <Button>
        <i:Interaction.Behaviors>
            <Behaviors:LoadImageBehavior Command="{Binding LoadImageCommand}"/>
        </i:Interaction.Behaviors>
    </Button>

答案 1 :(得分:0)

根据Bill Zhangs对行为的看法,我创建了一个非常控制并且允许重复使用的通用版本。 所需的程序集是

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

我创建了一个Trigger操作,将执行传递给事件处理程序:

using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
using System;

namespace Misc
{
   public class CommandWithEventAction : TriggerAction<UIElement>
   {
      public event Func<object, object> Execute;

      public static DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandWithEventAction), null);
      public ICommand Command
      {
         get
         {
            return (ICommand)GetValue(CommandProperty);
         }
         set
         {
            SetValue(CommandProperty, value);
         }
      }


      public static DependencyProperty ParameterProperty = DependencyProperty.Register("Parameter", typeof(object), typeof(CommandWithEventAction), null);
      public object Parameter
      {
         get
         {
            return GetValue(ParameterProperty);
         }
         set
         {
            SetValue(ParameterProperty, value);

         }
      }

      protected override void Invoke(object parameter)
      {
         var result = Execute(Parameter);
         Command.Execute(result);
      }

   }
}

为了避免自定义行为中的任何逻辑,这允许将任何事件挂接到事件回调,然后是命令调用。

XAML:

<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <misc:CommandWithEventAction Command="{Binding LoadImageCommand}" Parameter="Custom data"  Execute="CommandWithEventAction_OnExecute"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    Execute
</Button>

这会将装入对象的“自定义数据”字符串传递给名为

的函数
CommandWithEventAction_OnExecute

它的Func<object,object>签名可能会使用参数,需要返回一些内容,然后将其装入对象并传递给LoadImageCommand