Replies
Think I may have it.
In the InitializeLayout event, iterate through the bands and their columns, check the DataType property. If it's DateTime, then set the Format property accordingly.
To get the contents, call the band's GetRowEnumerator().OfType<UltraGridRow>(), and examine the cell values, if there are any, for the column in question. If TotalSeconds is zero, it's probably a date-only column. If the Milliseconds is zero, it's probably a seconds-precision time.
Any better method I'm not seeing?
Yeah, I had tried returning something unique in the ListName too, no luck.
And yet strangely, it's smart enough to requery the ICustomTypeDescriptor.GetProperties, for the same type. Go figure. I'll try mucking around with BindingManagerBase sometime, see if anything comes of it.
Say, while I've got you here, I'm running into an issue with data extracted from these dictionary pseudo-properties. The UltraGrid is rendering auto-generated datetime columns as date-only, with no time info. How do I change the default column format for datetime values? And is there any way to get it to examine the actual contents of the column first, even just the first row? Because often enough it really will be a date-only column, and then the date-only formatting would be preferable to "… 12:00:00 AM".
Correct.
> This all works great. But when I test with one property that is another ExpandoList of dynamic objects, the grid creates a new child band for it, but reuses the properties from the parent ExpandoObject to build the child band's columns, not the child's properties
Sorry, I should have posted a screenshot.
Yup. And indeed, it did work, for the top-level band. My original problem was that it would then clone that band for any child lists, instead of using the appropriate property descriptors for it.
No, I'm binding the grid to a BindingList of dictionaries. That's why I can add/delete rows, and the SetValue method in the property descriptor lets me change the dictionary entries as if they were real properties. In fact, one of the things I had to do in the custom JsonConverter was to rig it so that any non-list child objects were instead converted to a single-item list containing that object, otherwise the corresponding child band really would be bound to a dictionary.
Nah, probably won't bother. I've long since trashed that version of it anyhow, would have to rewrite it. Thanks anyway, though!
> You will not be able to add or delete rows from the grid
This is read-only. But I still could, since the grid is being passed a list of dictionaries masquerading as strongly-typed objects. Hence the PropertyDescriptor.GetValue() logic (there's a matching SetValue() method that I didn't type out here). It would have no trouble adding a new PropertyBag to the list and setting values using the properties obtained from other instances of the same band-type.
The customized BindingList didn't work for the child objects. I wound up being able to use a vanilla BindingList<object>. The logic is all in the object itself. Still the same object type for all bands, but I guess the grid doesn't cache/reuse property descriptions when the ICustomTypeDescriptor is in play.