1

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?

Community
  • 1
  • 1
bozalina
  • 89
  • 1
  • 13
  • Your class and Property names are the same. For testing, can you rename your classes and see if it still occurs? – Xcalibur37 Jul 19 '12 at 22:00
  • This example is simplified from my original code, which has properties named differently from their return types. The problem still occurs in this case. However, it will probably improve readability for this example, so I will update the code. – bozalina Jul 19 '12 at 22:07
  • I would say this is because B is instantiated as static. Therefore, once it has been instantiated it's contextual properties are disregarded. – Xcalibur37 Jul 19 '12 at 22:23

2 Answers2

1

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

Xcalibur37
  • 2,305
  • 1
  • 17
  • 20
  • That is also the solution I arrived at. I was hoping there would be a way to do it directly. You mention to stay away from statics because of the nature of DataObjectProvider. Could you clarify the reason for that? – bozalina Jul 20 '12 at 00:39
  • Well, to be fair I am being a bit subjective. It's because of the instance-based usage I have seen in most implementations. For what you are doing, I would personally use MVVM only because it gives me the most flexibility after the initial setup overhead of the ViewModel. – Xcalibur37 Jul 20 '12 at 00:42
1

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.

Joe Amenta
  • 4,662
  • 2
  • 29
  • 38