We are evaluating the Silverlight data visualization controls. So far we are very happy with how the pivot grid, charts and data selector controls works together in displaying and working with data. However, up to this point we have only worked with predefined (at compile time) object classes where the data properties are known.
As we understand the controls read the data source (we use the flat data source) and derives the available data properties from the object class present in the data set delivered.
But we also have another scenario where the properties of the object class to visualize is not known at compile time. Based on conditions in the database the data object to visualize must be built dynamically at run time, and can have any number of dimensions and measures.
.NET framework allows to add object class properties at run time using the TypeDescriptionProvider API in System.ComponentModel. This could solve our problem, but unfortunately this API is not available for Silverlight applications. Instead we have option of using the DynamicObject API and using TryGetMember function to return dynamic property values.
However, the latter requires that the Infragistics data controls know which properties are available to be able to query their values. Is there a way to tell for instance the data selector which dimension and measure properties are available on the data objects in the data source? Or is there another approach to supply a data source with data objects having a arbitrary number of dimensions and measures?
Excellent answer and suggestion. This solves our problem. We created a quick test on it, and now can create object collections on the fly from definitions in the database and then pass on to the data visualization controls.
Thank you very much for the quick and informative answer.
Hello,
Is there any chance to try the DynamicTypeBuilder in conjunction with DynamicTypePropertyInfo and DynamicCustomAttributeBuilder classes. You can find them in InfragisticsSL4.Olap.v10.2.dll / InfragisticsWPF4.Olap.v10.2.dll.
Your suggestion about DynamicObject is very interesting but I’m not sure when we can include functionality like this.
Here is a sample how you can use the DynamicTypeBuilder:
DynamicTypeBuilder typeBuilder =
new DynamicTypeBuilder
{
DynamicAssemblyName = "YourDynamicAssemblyName",
DynamicTypeName = "YourDynamicTypeName"
};
For each property you need you have to create instance of DynamicPropertyInfo class:
DynamicTypePropertyInfo propertyInfo =
new DynamicTypePropertyInfo
PropertyName = "YourDynamicTypePropertyName",
PropertyType = yourPropertyType
You also can decorate the property with attributes in order to propagate the metadata to the data selector. Display attribute like this one can be used for numeric types in order to set how the cell data is formatted.
DynamicCustomAttributeBuilder dynamicCustomAttributeBuilder =
new DynamicCustomAttributeBuilder(typeof(DisplayFormatAttribute))
NamedProperties = new[] { "DataFormatString" },
NamedPropertiesValues = new[] { "{0:C2}" }
For other type of properties where dimensions are created you can set DisplayAttribute in order to override the names displayed in data selector’s tree:
new DynamicCustomAttributeBuilder(typeof(DisplayAttribute))
NamedProperties = new[] { "Name" },
NamedPropertiesValues = new[] { "YourFriendlyPropertyName" }
Then add the attribute to attributes collection of the dynamic property
propertyInfo.DynamicCustomAttributeBuilders.Add(dynamicCustomAttributeBuilder);
Create an instance of your dynamic type:
Type dynamicType = typeBuilder.GenerateType(dynamicProperties);
Type listType = typeof(List<>);
Type genericListType = listType.MakeGenericType(dynamicType);
IList list = (IList)Activator.CreateInstance(genericListType);
Then for each data instance you have you need to create a instance of the dynamic type:
object myDynamicInstance = Activator.CreateInstance(dynamicType);
And set the values of its properties for each dynamic property you have:
PropertyInfo propertyInfo = dynamicType.GetProperty(propName);
propertyInfo.SetValue(myDynamicInstance, [yourPropertyValue], null);
Add the dynamic instance to the generic list we’ve created already:
list.Add(myDynamicInstance);
Set the list as FlatDataSource.ItemsSource.
I hope that will cover your needs but please let me know if you have any ideas or additional questions.
Regards.
Plamen.