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?
Hmm, well I can think of a roundabout way. There may be something easier/cleaner, but try this:
IProvideValueTarget
implementation via the IServiceProvider
.BindingExpression
for the bound property.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With