将自定义WPF控件中的事件绑定到ViewModel中的命令

3

我有一个自定义控件,其中包含一个事件。 我有一个使用该自定义控件的窗口。 该窗口绑定到一个视图模型。 我希望将自定义控件的事件直接传递给视图模型上的ICommand。 显然,我很迟钝,无法想出如何做到这一点。任何帮助都非常欢迎。

谢谢

2个回答

2
如果只是一次性的话,你可以使用一个简单的事件处理程序:
<some:CustomControl SuperDuper="OnSuperDuper" />

使用代码后端
private void OnSuperDuper(object sender, EventArgs e)
{
  _theCommand.Execute(null, (IInputElement)sender);
}

如果你想针对特定事件多次执行此操作,我建议使用附加属性。
<some:CustomControl my:AttachedEvents.SuperDuperCommand="{Binding TheCommand}" />

所附加的属性仅为:

// use propa snippet to build this quickly
public static ICommand GetSuperDuperCommand(DependencyObject obj) { return (ICommand)obj.GetValue(SuperDuperCommandProperty); }
public static void SetSuperDuperCommand(DependencyObject obj, ICommand value) { obj.SetValue(SuperDuperCommandProperty, value); }
public static readonly DependencyProperty SuperDuperCommandProperty = DependencyProperty.RegisterAttached("SuperDuperCommand", typeof(ICommand), typeof(AttachedEvents), new PropertyMetadata
{
  PropertyChangedCallback = (obj, e) =>
  {
    if(oldCommand==null) ((CustomControl)obj).SuperDuper += OnSuperDuper;
    if(newCommand==null) ((CustomControl)obj).SuperDuper -= OnSuperDuper;
  }
});

private void OnSuperDuper(object sender, EventArgs e)
{
  var control = (CustomControl)sender;
  GetSuperDuperCommand(sender).Execute(null, sender));
}

您可以进一步推广此方法,使用MarkupExtension将任何事件映射到任何命令。 这是个想法:

<some:CustomControl SuperDuper="{lib:CommandWrapper {Binding TheCommand}}" />

代码如下:
public class CommandWrapper : MarkupExtension
{
  public BindingBase CommandBinding { get; set; }

  public CommandWrapper() {}
  public CommandWrapper(BindingBase commandBinding) { CommandBinding = commandBinding; }

  public object ProvideValue(IServiceProvider serviceProvider)
  {
    return new EventHandler((obj, e) =>
    {
      // Evaluate CommandBinding against obj, fire command
    });
  }
}

你可以充实细节。请注意,你可能想将实际的事件处理程序类型传递给CommandWrapper,并使用反射构造适当的委托,而不是简单地说“new EventHandler”。
我不确定XAML解析器是否允许你使用MarkupExtension设置事件,所以这个最后的解决方案可能并不像这样简单。但如果不行,它可以与附加属性结合使用,如下所示:
<some:CustomControl lib:CommandWrapper.Add="{lib:CommandWrapper SuperDuper,{Binding TheCommand}}" />

这一定会奏效:CommandWrapper.Add将从由标记扩展创建的CommandWrapper接收事件名称,并可以创建相应的映射。

-1

3
网站宕机了。以下是必要部分的翻译答案。 - LueTm

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