locked
How can I bind to member classes of a class RRS feed

  • Question

  • I want to encapsulate all the data binding, validation, conversion, etc. objects for a piece of data under a single class, then reference these child objects as needed in XAML.

    For Example:

        I can implement a collection like this

    ***

        public class MyModes : ObservableCollection<string>
        {
            public MyModes()
            {
                Add("Mode One");
                Add("Mode Two");
            }
        }

    And bind it to a combo box, like this

          <Grid.Resources>
            <ObjectDataProvider x:Key="Modes" ObjectType="{x:Type src:MyModes}"/>
          </Grid.Resources>

          ....

          ItemsSource="{Binding Source={StaticResource Modes}}" IsSynchronizedWithCurrentItem="true">

    ***

    Which works fine unless I want another level of encapsulation/indirection. The compiler complains if I do something like this:

    ***

    public class ModesHolder
    {
        public MyModes TheModes; // the MyModes collection is now a member of ModesHolder
    }

    <ObjectDataProvider x:Key="Modes" ObjectType="{x:Type src:ModesHolder.TheModes}"/>

    ***

    Error 2 Cannot find the type 'src:TimingModeSetting.TimingModes'. Note that type names are case sensitive. Line 8 Position 43. 

    I can see that I am technically referencing a class, so the error makes sense.

    What I really want is the parent class to be instantiated and the child object/collection to be used. Can this be done?

    Thanks

    NIK

     

     

     

    Friday, August 11, 2006 6:08 PM

Answers

  • If the ModesHolder.TheModes is a static property you can reference it like this.

    <ObjectDataProvider x:Key="Modes" ObjectType="{x:Type src:ModesHolder}"/>

    <Binding Source="{StaticResource Modes}" Path="TheModes"/>

    or in your particular case...

    ItemsSource="{Binding Source={StaticResource Modes}, Path=TheModes}"

    Friday, August 11, 2006 6:23 PM
  • Marking a property as static (shared in VB) does not prevent it from being dynamic. What it means is that its shared across all instances of a class.

    I would avoid using inner classes if they are designed to be used externally it's just messy.

    So if you had a class like

    MachineSettings

    You could define all of the properties as static...and in fact define the class as being static itself to prevent someone from thinking that they need an instance of the class. You can then use the ObjectDataProvider to create the bindings.

    Another alternative is instead of using the ObjectType property of ObjectDataProvider, you use ObjectInstance. Then you can bind to the properties even if they are not static. You'd probably assign object Instance in a code behind.

    Going beyond that if your control is specifically tied to a particular object you can just set the DataContext on your control and use {Binding PropertyName} markup to bind to particular properties on your control.

    Another useful convention is to create an enumeration for a multistate (more than just on/off or true/false) property. Then you can do all kinds of tricks with styles using triggers based on the value of the property.

    If you'd like to discuss more, we can get into more detail over email so that the proprietary nature of what you're doing isn't floating around on a forum. Send me a message at mbrown77@gmail.com.

    Friday, August 11, 2006 9:24 PM

All replies

  • If the ModesHolder.TheModes is a static property you can reference it like this.

    <ObjectDataProvider x:Key="Modes" ObjectType="{x:Type src:ModesHolder}"/>

    <Binding Source="{StaticResource Modes}" Path="TheModes"/>

    or in your particular case...

    ItemsSource="{Binding Source={StaticResource Modes}, Path=TheModes}"

    Friday, August 11, 2006 6:23 PM
  • Thanks for the quick response. Hey Mike, you are just all over anything binding related huh? 

    :)

    Can you elaborate on "static property"?

    NIK

     

     

     

     

    Friday, August 11, 2006 7:21 PM
  • LOL, well I'm enjoying all the possibilities with WPF. And I'm just working on basic controls, you should see some of the stuff our company is doing with 3D...oh wait you will soon enough . Anyway, here is an example of something I did similar to what you're trying to do. This is just a test class to show off the PowerGrid. I declared a static collection of Contacts (basically a class that holds information that would go into an employee extension list). And in the static constructor, I initialize the collection. Now the collection can be accessed in XAML the XAML used to access the collection follows the code.

    public class ContactTest

    {

    private static List<Contact> m_Contacts;

    public static List<Contact> Contacts

    {

    get { return m_Contacts; }

    }

    static ContactTest()

    {

    m_Contacts = new List<Contact>();

    String tmpImage = @"c:\code\wpftoolbelt\wpftoolbeltdemoapp\bin\debug\Images\Sunset.jpg";

    String tmpImage1 = @"Images\Winter.jpg";

    m_Contacts.Add(new Contact("1", "Joe", "Schmoe", "147", tmpImage));

    m_Contacts.Add(new Contact("2", "John", "Doe", "154", tmpImage1));

    m_Contacts.Add(new Contact("3", "Albert", "Hacker", "113", tmpImage));

    m_Contacts.Add(new Contact("4", "Mike", "Brown", "112", tmpImage1));

    }

    }

     

    <Window.Resources>

    <ObjectDataProvider ObjectType="{x:Type local:ContactTest}" x:Key="odp1"/>

    </Window.Resources>

    <StackPanel Orientation="Vertical">

    <SG:PowerGrid Name="PowerGrid" Items="{Binding Source={StaticResource odp1}, Path=Contacts}" >

    ...

    </SG:PowerGrid>

    ...

    </StackPanel>

    </Window>

    As you see the binding for the PowerGrid Items Attribute I set the source to be odp1 and the path is Contacts. You can also use the ObjectDataProvider to create an instance of a class, call a method and bind to the results of that method.

    Friday, August 11, 2006 7:38 PM
  • Sounds like I should explore this.

    "You can also use the ObjectDataProvider to create an instance of a class, call a method and bind to the results of that method."

    I have about 600 (potentially inter-related) settings/commands for (several models) of a piece of high-tech hardware that our software controls, and I'm trying to get all the business logic moved out of the UI as much as possible, thus all the questions about Binding and Control creation. Unfortunately, a lot of the data is not static, but derived or modified at run time.

    My boss thought internal classes might provide a solution for being able to reference a type within a larger class. Thoughts?

    Thx

    NIK

     

     

     

    Friday, August 11, 2006 8:50 PM
  • Marking a property as static (shared in VB) does not prevent it from being dynamic. What it means is that its shared across all instances of a class.

    I would avoid using inner classes if they are designed to be used externally it's just messy.

    So if you had a class like

    MachineSettings

    You could define all of the properties as static...and in fact define the class as being static itself to prevent someone from thinking that they need an instance of the class. You can then use the ObjectDataProvider to create the bindings.

    Another alternative is instead of using the ObjectType property of ObjectDataProvider, you use ObjectInstance. Then you can bind to the properties even if they are not static. You'd probably assign object Instance in a code behind.

    Going beyond that if your control is specifically tied to a particular object you can just set the DataContext on your control and use {Binding PropertyName} markup to bind to particular properties on your control.

    Another useful convention is to create an enumeration for a multistate (more than just on/off or true/false) property. Then you can do all kinds of tricks with styles using triggers based on the value of the property.

    If you'd like to discuss more, we can get into more detail over email so that the proprietary nature of what you're doing isn't floating around on a forum. Send me a message at mbrown77@gmail.com.

    Friday, August 11, 2006 9:24 PM