5

好的,我不想在我的 MVVM ViewModels 中有一堆 ICommand,所以我决定为 WPF 创建一个 MarkupExtension,你给它一个字符串(方法的名称),它会给你一个执行方法的 ICommand。

这是一个片段:

public class MethodCall : MarkupExtension
{
    public MethodCall(string methodName)
    {
        MethodName = methodName;
        CanExecute = "Can" + methodName;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        Binding bin = new Binding { Converter = new MethodConverter(MethodName, CanExecute) };

        return bin.ProvideValue(serviceProvider);
    }
}

public class MethodConverter : IValueConverter
{
    string MethodName;
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //Convert to ICommand
        ICommand cmd = ConvertToICommand();
        if (cmd == null)
            Debug.WriteLine(string.Format("Could not bind to method 'MyMethod' on object", MethodName));
        return cmd;
    }
}

它工作得很好,除非绑定失败(例如你输入错误)。

当您在 xaml 中执行此操作时: {Binding MyPropertyName}只要绑定失败,您就会在输出窗口中看到。它会告诉您 propertyName 类型名称等。

MethodConverter 类可以告诉您失败的方法的名称,但不能告诉您源对象类型。因为该值将为空。

我不知道如何存储源对象类型,所以对于以下类

public class MyClass
{
    public void MyMethod()
    {
    }
}

和以下xaml:

<Button Command={d:MethodCall MyMethod}>My Method</Button>

它目前说:

"Could not bind to method 'MyMethod' on object

但我想说:

"Could not bind to method 'MyMethod' on object MyClass

有任何想法吗?

4

2 回答 2

2

嗯,我可以想到一个迂回的方式。可能有一些更容易/更清洁的东西,但试试这个:

  1. 通过. IProvideValueTarget_IServiceProvider
  2. 使用目标信息来解析BindingExpression绑定属性。
  3. 使用 上的DataItem属性BindingExpression来获取源对象。

就像是:

var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
var bindingExpression = BindingOperations.GetBindingExpression(provideValueTarget.TargetObject, (DependencyProperty)provideValueTarget.TargetProperty);
var source = bindingExpression.DataItem;

可怕,但它应该工作。很可能有一项服务可以为您执行此操作,但在快速浏览 MSDN 后我找不到。

于 2010-03-29T18:12:15.580 回答
0

它不是绑定,对于命令,您不需要绑定,因为命令对象有一个CanExecuteChanged事件。

public override object ProvideValue(IServiceProvider serviceProvider)  
{    
    ICommand cmd = ConvertToICommand();
    return cmd;
}

确保ConverTOICommand总是返回一些东西。是时候考虑一​​个空命令或其他东西了。

于 2011-04-22T18:56:50.790 回答