获取WPF绑定的值

Jos*_*ose 5 c# data-binding wpf mvvm markup-extensions

好吧,我不想在我的MVVM ViewModels中使用一堆ICommands,所以我决定为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

它很有效,除非绑定失败(例如你输入错误).

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

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

我无法弄清楚如何为以下类存储源对象类型

public class MyClass
{
    public void MyMethod()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

和以下xaml:

<Button Command={d:MethodCall MyMethod}>My Method</Button>
Run Code Online (Sandbox Code Playgroud)

它目前说:

"Could not bind to method 'MyMethod' on object
Run Code Online (Sandbox Code Playgroud)

但我想说:

"Could not bind to method 'MyMethod' on object MyClass
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Ken*_*art 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;
Run Code Online (Sandbox Code Playgroud)

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