2010-05-12 419 views
2

我有一个具有事件的自定义控件。 我有一个使用该自定义控件的窗口。 窗口绑定到视图模型。 我想从自定义控件直接到我的viewmodel上的ICommand事件。 我明显在这里密集,因为我无法弄清楚如何做到这一点。任何援助是最受欢迎的。将自定义WPF控件中的事件绑定到ViewModel中的命令

谢谢

回答

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 
    }); 
    } 
} 

可以充实细节。请注意,不是简单地说“新的EventHandler”,您可能希望将实际的事件处理程序类型传递给CommandWrapper,并使用反射来构造相应的代理。

我不完全确定XAML解析器会让您使用MarkupExtension设置事件,所以最后的解决方案实际上可能不会实现这一点。但是,如果没有,也可以用像这样的附加属性组合:

这肯定会工作:CommandWrapper.Add将被标记扩展创建的CommandWrapper接收事件名称,可以建立相应的映射。