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

时间:2010-05-12 15:46:44

标签: .net wpf mvvm

我有一个有事件的自定义控件。 我有一个使用该自定义控件的窗口。 该窗口绑定到视图模型。 我想将自定义控件中的事件直接发送到我的viewmodel上的ICommand。 我显然在这里很密集,因为我无法弄清楚如何做到这一点。非常欢迎任何帮助。

由于

2 个答案:

答案 0 :(得分: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 :(得分:-1)

如果要将事件路由到命令,可以使用附加属性。我使用此示例为ComboBox SelectionChanged事件添加命令支持:

http://blog.fossmo.net/post/How-to-create-an-attached-property-in-WPF-using-a-ComboBox.aspx

干杯。