Question

This question may be a duplicate of Creating an instance of a nested class in XAML. This question and the related MSDN documentation are concerned with nested types. In this example, the types themselves are not nested, but the syntax seems familiar. Whether that justifies a separate question and answer is unknown to me.

I would like to access a nested property using an ObjectDataProvider. I can access a static property on a type, but accessing an instance property through a static property on a type results in compilation errors.

For example, take the following three classes.

public static class A
{
   static A()
   {
      BProperty = new B();
   }

   public static B BProperty { get; private set; }
}

public class B
{
   public B()
   {
      CProperty = new C();
   }

   public C CProperty { get; private set; }

   public string GetValue(string arg)
   {
      return arg + " from B";
   }
}

public class C
{
   public string GetValue(string arg)
   {
      return arg + " from C";
   }
}

Creating an ObjectDataProvider for BProperty on A can be accomplished using the following XAML.

<Window.Resources>
   <ObjectDataProvider x:Key="provider"
                       ObjectInstance="{x:Static Member=local:A.BProperty}"
                       MethodName="GetValue">
      <ObjectDataProvider.MethodParameters>
         <System:String>string argument</System:String>
      </ObjectDataProvider.MethodParameters>
   </ObjectDataProvider>
</Window.Resources>
<Grid>
   <Label Content="{Binding Source={StaticResource provider}}" />
</Grid>

Running this code produces a label with the text: "string argument from B".

If I set provider's ObjectInstance to "{x:Static Member=local:A.BProperty.CProperty}" or "{x:Static Member=local:A.BProperty+CProperty}" I receive compilation errors.

How can I access CProperty on A's instance of BProperty from the ObjectDataProvider?

Was it helpful?

Solution

The best you can do is this:

<Window.Resources>
    <ObjectDataProvider x:Key="provider"
                   ObjectType="{x:Type local:A}"
                   MethodName="GetCValue">
        <ObjectDataProvider.MethodParameters>
            <System:String>string argument</System:String>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>


public class A
{
    public A()
    {
        BProperty = new B();
    }

    public B BProperty { get; private set; }

    public string GetCValue(string arg)
    {
        return BProperty.CProperty.GetValue(arg);
    }
}

public class B
{
    public B()
    {
        CProperty = new C();
    }

    public C CProperty { get; private set; }

    public string GetValue(string arg)
    {
        return arg + " from B";
    }
}

public class C
{
    public string GetValue(string arg)
    {
        return arg + " from C";
    }
}

I would stay away from statics in this type of implementation given the nature of ObjectDataProvider

If you want to use a tiered object, consider implementing the MVVM pattern and implementing all your objects in a ViewModel instead.

Check out this article for more details on ObjectDataProvider: http://msdn.microsoft.com/en-us/magazine/cc163299.aspx

OTHER TIPS

Do it in 2 steps:

<Window.Resources>
   <ObjectDataProvider x:Key="providerOfC"
                       ObjectInstance="{x:Static Member=local:A.BProperty}"
                       MethodName="get_CProperty" />

   <ObjectDataProvider x:Key="provider"
                       ObjectInstance="{StaticResource providerOfC}"
                       MethodName="GetValue">
      <ObjectDataProvider.MethodParameters>
         <System:String>string argument</System:String>
      </ObjectDataProvider.MethodParameters>
   </ObjectDataProvider>
</Window.Resources>
<Grid>
   <Label Content="{Binding Source={StaticResource provider}}" />
</Grid>

providerOfC gets you as far as A.BProperty.CProperty

provider then calls GetValue("string argument") on that instance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top