获取 WPF 绑定的值

发布于 2024-08-27 04:08:34 字数 1631 浏览 11 评论 0原文

好吧,我不想在我的 MVVM ViewModel 中使用一堆 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

有什么想法吗?

Ok, I didn't want a bunch of ICommands in my MVVM ViewModels so I decided to create a MarkupExtension for WPF that you feed it a string(the name of the method), and it gives you back an ICommand that executes the method.

here's a snippet:

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

It works great, except when the binding fails(e.g. you mistype).

When you do this in xaml:
{Binding MyPropertyName} you see in the output window whenever the binding fails. and it tells you the propertyName the Type name etc.

The MethodConverter Class can tell you the name of the method that failed, but it can't tell you the source object type. Because the value will be null.

I can't figure out how to store the source object type so for the following class

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

and the following xaml:

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

It currently says:

"Could not bind to method 'MyMethod' on object

but I would like it to say:

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

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寄风 2024-09-03 04:08:34

嗯,我可以想个迂回的办法。可能有更简单/更干净的方法,但请尝试以下操作:

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

比如:

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

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

Hmm, well I can think of a roundabout way. There may be something easier/cleaner, but try this:

  1. Get the IProvideValueTarget implementation via the IServiceProvider.
  2. Use the target information to resolve a BindingExpression for the bound property.
  3. Use the DataItem property on the BindingExpression to get the source object.

Something like:

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

Awful, but it should work. There may well be a service that does this for you, but I couldn't find one after a quick look in MSDN.

浊酒尽余欢 2024-09-03 04:08:34

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

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

确保 ConverTOICommand 始终返回一些内容。是时候考虑一​​下空命令之类的了。

It's not a Binding, and for commands you don't need bindings because the command objects have a CanExecuteChanged event.

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

make sure that ConverTOICommand always returns something. Time to think about a null command, or something.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文