views:

1908

answers:

3

Good morning,

I am working with an object which has sub objects with in (see example below), I am attempting to bind a List to the datagrid. When I bind the List<>, in the cell that contains the subObject I see the following Value ... "namespace.subObject" ... the string values display correctly.

Ideally I would like to see the "Description" property of the subObject in the datacell, how can I map the subObject.Description to show in the dataCell?

public class subObject
{
   int id;
   string description;

   public string Description
   { get { return description; } }
}

public class rootClass
{
   string value1;
   subObject value2;
   string value3;

   public string Value1
   { get { return value1; } }

   public subObject Value2
   { get { return value2; } }

   public string Value3
   { get { return value3; } }
}

Thank you for your assistance,

Scott Vercuski

+4  A: 

If I'm not mistaken, it shows the result of calling .ToString() on your subObject, so you can override that to return the contents of Description.

Have you tried just binding to Value1.Description? (I'm guessing it doesn't work).

I have a class that can be used instead of List when binding, that will handle this, it implements ITypedList, which allows a collection to provide more "properties" for its objects, including calculated properties.

If no easy solution crops up, I'll post a link to my repository later when I'm at my home computer.

Edit: Ok, the current version of the files I have are here:

http://code.google.com/p/lvknet/source/browse/#svn/trunk/LVK/Collections

Depending on your browser you will get either a warning or an error message saying something about the certificate. The reason is that the certificate doesn't match the url and I'm too lazy to try to figure out if there is something I can do about it. It's a subversion repository so nothing malicious should be there but the usual guidelines are in effect.

You'll need a username and password, both are guest in lower-case.

The files you want are the ones near the bottom of that list, TypedList*.

Unfortunately (for you), I tend to write classes and code in that class library by reusing other bits I have already written, so you'll need to download the first few files and if those doesn't compile, either try taking something out or grab a few more files. There are namespaces and such further up the hierarchy if you need them.

To use:

List<rootClass> yourList = ...
TypedListWrapper<rootClass> bindableList = new TypedListWrapper<rootClass>(yourList);
bindableList.BindableProperties = "Value1;Value2.Description;Value3.Description";
gridView1.DataSource = bindableList;

Basically you bind to an instance of TypedList<T> instead of List<T>, and adjust the BindableProperties property. I have some changes in the work, including one that just builds up BindableProperties automatically as it goes, but it isn't in the trunk yet.

You can also add calculated properties, like this:

yourList.AddCalculatedProperty<Int32>("DescriptionLength",
    delegate(rootClass rc)
    {
        return rc.Value2.Description.Length;
    });

or with .NET 3.5:

yourList.AddCalculatedProperty<Int32>("DescriptionLength",
    rc => rc.Value2.Description.Length);
Lasse V. Karlsen
Just for info, ITypedList is mainly 1.1; in 2.0 you can use `TypeDescriptionProvider` on the underlying type (i.e. the T in the List<T>) to do the same.
Marc Gravell
Glad to see I'm not the only fool to have explored the depths of TypeDescriptor, though ;-p
Marc Gravell
I will look into TypeDescriptionProvider then :)
Lasse V. Karlsen
You can get a quick intro if you look at the `HyperDescriptor` code (just search). Once you've got as far as GetProperties() it should be familiar ;-p
Marc Gravell
+2  A: 

I'm not sure whether you are using ASP.NET, but if yes, then you can use a template column and the Eval() method to display values of nested objects. E.g. to display the Description property of the subObject:

<asp:GridView ID="grid" runat="server" AutoGenerateColumns="true">
  <Columns>
    <asp:TemplateField>
      <ItemTemplate>
        <asp:Literal Text='<%# Eval("Value2.Description") %>' runat="server" />
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>
M4N
+3  A: 

Since you mention DataGridViewColumn (tags), I assume you mean winforms.

Accessing sub-properties is a pain; the currency-manager is bound to the list, so you only have access to immediate properties by default; however, you can get past this if you absolutely need by using a custom type descriptor. You would need to use a different token too, like "Foo_Bar" instead of "Foo.Bar". However, this is a major amount of work that requires knowledge of PropertyDescriptor, ICustomTypeDescriptor and probably TypeDescriptionProvider, and almost certainly isn't worth it,

The simplest fix is to expose the property as a shim / pass-thru:

public string Value2Description {
    get {return Value2.Description;} // maybe a null check too
}

Then bind to "Value2Description" etc.

Marc Gravell