1

Is it possible to use a method of the DataContext in a binding?

E.g. the signature public bool ProjectIsActive(int number) [note: not static], can it be declared in a binding?

EDIT: Following the suggestion of ywm and Sheridan I tried adding a resource to my Window with name _this.
I changed the signature to public bool ProjectIsActive(object number).

<Window.Resources>
<ObjectDataProvider x:Key="ProjectIsActive"
                    ObjectInstance="_this.DataContext"
                    MethodName="ProjectIsActive">
    <ObjectDataProvider.MethodParameters>
        <sys:Object></sys:Object>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>

Then the Binding of the Trigger is set as:

<Binding  Source="{StaticResource ProjectIsActive}" Path="MethodParameters[0]" BindsDirectlyToSource="true" />

It gives the error: System.Windows.Data Error: 35 : ObjectDataProvider: Failure trying to invoke method on type; Method='ProjectIsActive'; Type='String'; Error='No method was found with matching parameter signature.' MissingMethodException:'System.MissingMethodException: Method 'System.String.ProjectIsActive' not found. at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at System.Windows.Data.ObjectDataProvider.InvokeMethodOnInstance(Exception& e)'

The method signature of ObjectDataProvider.MethodParameters doesn't distinghuish return value from input paramter, I don't know how to proceed.

NOTE: The objective can be also achieved by using a MultiValueConverter and casting in the Convert method etc. I was only curious because binding to a property is so easy, and binding to a method [in my case] so difficult. There are also still better ways to avoid a call to a method.

Gerard
  • 13,023
  • 14
  • 72
  • 125

3 Answers3

3

You can use the ObjectDataProvider to access data returned from a method.

<Window.Resources>
  <ObjectDataProvider x:Key="colors"
  ObjectType="{x:Type local:ColorHelper}"
  MethodName="GetColorNames"/>
</Window.Resources>
ywm
  • 1,107
  • 10
  • 14
  • All well, but the point is that in my case I want the local:ColorHelper to be the instance of my DataContext. I believe the ObjectDataProvider uses the default ctor and creates a new class. I'll try `ObjectInstance="DataContext"`. – Gerard Nov 12 '13 at 10:31
  • @Gerard How did you get on with the ObjectInstance? – ywm Nov 12 '13 at 11:32
  • That is correct @Gerald. It uses a new instance each time, taking the default ctor. – Robetto Feb 06 '17 at 11:47
1

In addition to @ywm's answer, you can also supply input parameters for your method in this way:

xmlns:System="clr-namespace:System;assembly=mscorlib"

...

<Window.Resources>
    <ObjectDataProvider x:Key="ProjectIsActiveMethod" 
        ObjectType="{x:Type System:Boolean}" IsAsynchronous="True" 
        MethodName="ProjectIsActive">
        <ObjectDataProvider.MethodParameters>
            <System:Int32>10</System:Int32>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Does also not solve the original poster's question on whether one can use a DC object to let ObjectDataProvider do a call on. – Robetto Feb 06 '17 at 11:48
0

It seems like there is no way to do it unless you write your own ObjectDataProvider that can take a biding.

This is result of that post, which explains how to write a FreezableProxy to accomplish it with the OBjectDataProvider.

Robetto
  • 739
  • 7
  • 20