Search code examples
c#objectlistview

How to create a dynamic model for ObjectListView


I searched for hours but either my programming approach is wrong or I didn't have the correct searching ideas...

Lot of time ago, I discovered ObjectListView as an nice alternative to normal ListView. My Problem in my current Project:

I didn't have an static model class. I have a lot of objects of different kinds. Each kind of object has different attributes. In my ObjectListView I want to show the Name of the Object and its attributes, a row for each object of given kind. (For one kind of a Object, the attributes are the same)

For my Model of ObjectListView I tried following Mini-example (using "num" and "txt" as AspactName):

using System.Dynamic;
[...]
private void addItems()
{
    dynamic expando = new ExpandoObject();
    expando.num = 1;
    expando.txt = "Element";

    List<ExpandoObject> lst = new List<ExpandoObject>();
    lst.Add(expando);
    olv.SetObjects(lst);
}

ObjectListView adds an Row but doesn't show up the text of the Properties num and txt.

Any Idea to solve this problem? Is there another approach to show elements of a List (like Object.Attributes) as Columns using ObjectListView?

Thank you in advance.


Okay, Thank you Klaus, following your idea in my mind and searching again for special Objects and ObjectListView pointed me to AspectGetterDelegates

I found a solution working for the first time: adding following AspectGetter Delegate, the ObjectListView shows the information of my dynamicaly generated Properties:

olv.GetColumn(0).AspectGetter = delegate (dynamic er) { return er.Nummer; };
olv.GetColumn(1).AspectGetter = delegate (dynamic er) { return er.Text; };

If someone has the same Problem, here are two useful Methods for Setting and Getting Properties from ExpandoObjects:

    public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
    {

        var expandoDict = expando as IDictionary<string, object>;
        if (expandoDict.ContainsKey(propertyName))
            expandoDict[propertyName] = propertyValue;
        else
            expandoDict.Add(propertyName, propertyValue);
    }

    public static object GetProperty(ExpandoObject expando, string propertyName)
    {

        var expandoDict = expando as IDictionary<string, object>;
        if (expandoDict.ContainsKey(propertyName))
            return expandoDict[propertyName];
        else
            return null;
    }

Solution

  • I am also a user of ObjectListView and find it very good, but had a similar problem recently where I had such dynamic objects. In fact, in my case I did not know at all the property names in code, this only came from the data and I had the complication of having to flatten out the data which was in a parent child hierarchy.

    My problem is here: Flattern child/parent data with unknown number of columns

    The solution for me was to use a variant of OLV which is DataListView (appears not to be available via NuGet, but is as download from the OLV website http://objectlistview.sourceforge.net/cs/download.html)

    Then, once I had my data in a Dynamic object (like you have) I then converted this into a DataTable which I could bind to the DataListView

    My data was stored in:

    List<dynamic> allRecords = new List<dynamic>();
    //Build my dynamic data here
    

    I converted this to a DataTable:

    private DataTable GetDataTableFromObject(List<dynamic> allRecords)
    {
        DataTable dt = new DataTable();
        foreach (dynamic record in allRecords)
        {
            DataRow dr = dt.NewRow();
            foreach (dynamic item in record)
            {
                var prop = (IDictionary<String, Object>)item;
                if (!dt.Columns.Contains(prop["Column_name"].ToString())) //Column_Name = Property name
                {
                    dt.Columns.Add(new DataColumn(prop["Column_name"].ToString()));
                }
    
                dr[prop["Column_name"].ToString()] = prop["Data"];  //Data = value
            }
            dt.Rows.Add(dr);
        }
        return dt;
    }
    

    Then I added it to the DataListView

    this.dataListView1.DataSource = GetDataTableFromObject(allRecords);
    this.dataListView1.RebuildColumns();