Get value for WPF binding

Well, I didnโ€™t want to have a bunch of ICommands in MVMM ViewModels, so I decided to create MarkupExtension for WPF so that you pass it a string (method name) and it returns you ICommand, which 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 does not work (for example, you are mistaken).

When you do this in xaml: {Binding MyPropertyName} you see in the output window whenever the failure fails. and it tells you the property nameName, etc.

The MethodConverter class can tell you the name of the method that failed, but it cannot specify the type of the source object. Since the value will be zero.

I can't figure out how to save the type of the source object, so for the next class

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

and the following haml:

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

He currently says:

 "Could not bind to method 'MyMethod' on object 

but I would like him to say:

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

Any ideas?

+4
source share
2 answers

Hm, well, I can think of a circular path. Something might be easier / cleaner, but try the following:

  • Get the implementation of IProvideValueTarget using IServiceProvider .
  • Use the target information to resolve the BindingExpression for the associated property.
  • Use the DataItem property on BindingExpression to get the source object.

Sort of:

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

Terrible, but it should work. There may be a service that will do this for you, but I could not find it after a quick look at MSDN.

+1
source

This is not a binding, and for commands you do not need bindings, because command objects have a CanExecuteChanged event.

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

make sure ConverTOICommand always returns something. Time to think about a zero team or something.

0
source

Source: https://habr.com/ru/post/1305466/


All Articles