Inheriting from DataFactory

Grids for WPF Forum

Posted 14 years ago by Jose Simas
Avatar
Hi,

I am trying to add a number of categories to the PropertyGrid and under each one of them add a few properties. I am able to add the categories but I am unable to add items under each one of them.

I created a class that inherits from DataFactory and I am overriding GetProperties and GetDataAccessors based on this post:

http://www.actiprosoftware.com/support/forums/viewforumtopic.aspx?ForumTopicID=3929

The overrides are:

protected override IList<IPropertyDataAccessor> GetProperties(object value, DataFactoryOptions options)
{
//not sure what I should be doing here but it is abstract.
return null;
}

public override IList<IDataAccessor> GetDataAccessors(object[] values, DataFactoryOptions options)
{
var cols = values[0] as DataSetColumn[];
if (cols == null) return null;

var list = new List<IDataAccessor>();
for (int i = 0; i < cols.Length; i++)
{
var cat = new CategoryDataAccessor(cols[i].Label);
list.Add(cat);

var item = new PropertyDescriptorDataAccessor(cat, "Max");
item.Value = cols[i].DataSetColumnStats.MaxValue;
list.Add(item);
}
return list;
}

The code fails at the line "item.Value = cols[i].DataSetColumnStats.MaxValue;" with the exception "Object reference not set to an instance of an object." (StackTrace at the bottom of the post). The source of the exception is in the item.Value property (or deeper).

I must be missing a step here. Would you please let me know what I have to do?


StackTrace:

at ActiproSoftware.Windows.Controls.PropertyGrid.Primitives.ReflectionPropertyDescriptor.get_PropertyType()
at System.ComponentModel.PropertyDescriptor.get_Converter()
at ActiproSoftware.Windows.Controls.PropertyGrid.Primitives.PropertyDescriptorDataAccessor.set_ValueInternal(Object value)
at ActiproSoftware.Windows.Controls.PropertyGrid.Primitives.CachedPropertyDataAccessorBase.set_Value(Object value)
at GeneXproTools.Controls.Data.DataManagement.MyFactory.GetDataAccessors(Object[] values, DataFactoryOptions options)

Comments (4)

Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Jose,

The DataFactory class provides categorization and property merging (when multiple objects are assigned to SelectedObjects). There are two derivations to this class, TypeDescriptorFactory and TypeReflectionFactory. Each of these overrides the GetProperties(object,DataFactoryOptions) methods to provide the list of properties for a given object. The DataFactory.GetDataAccessors(object[],DataFactoryOptions) method calls GetProperties(object,DataFactoryOptions) and performs the categorization and property merging.

It sounds like you should create an object that implements the IDataFactory interface. Since you are not leveraging the features of the concrete DataFactory class or it derivations.

As far as the exception, the following line create a PropertyDescriptorDataAccessor that can be used to get/set a property named "Max" on the cat object. Since cat is a CategoryDataAccessor, there is no such property as "Max", thus the exception.
var item = new PropertyDescriptorDataAccessor(cat, "Max"); 
You should probably change this to the following and remove the line where you set the Value:
var item = new PropertyDescriptorDataAccessor(cols[i].DataSetColumnStats, "MaxValue"); 
You can think of the PropertyDescriptorDataAccessor as a fancy way of calling a property's getter and/or setter, which is ulimately leveraged by the PropertyGrid.


Actipro Software Support

Posted 14 years ago by Jose Simas
Avatar
Hi,

Thank you for the explanation and the code. I changed my for loop to:

var list = new List<IDataAccessor>();
for (int i = 0; i < cols.Length; i++)
{
    var cat = new CategoryDataAccessor(cols[i].Label);
    list.Add(cat);
    var item = new PropertyDescriptorDataAccessor(cols[i].DataSetColumnStats, "MaxValue");
    cat.Accessors.Add(item);
}
And now I get the desired effect but I need to change the display name of "item" to Maximum instead of MaxValue and I will also need to format the value (round the value to 6 decimal places, for example). How can I do that? DisplayName is read only and I don't see a way to format the value (without creating a class with the formatted value).

Thanks,
Jose
Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Jose,

You would either need to add the DisplayNameAttribute to your property, like so:
[DisplayName("Maximum")]
public int MaxValue { get; set; }
Or, you would have to create a class that derives from PropertyDescriptorDataAccessor, something like:
public class MyPropertyDescriptorDataAccessor : PropertyDescriptorDataAccessor {

    private string displayName;
    
    public PropertyDescriptorDataAccessor(object target, string propertyName, string name)
        : this(target, propertyName, null) {
        this.displayName = name;
    }
    
    protected override string DisplayNameInternal {
        get {
            if (!string.IsNullOrEmpty(this.displayName))
                return this.displayName;
            return base.DisplayNameInternal;
        }
    }
}
The formatting or presentation of the value should be done with a property editor. The DataFactory and accessors are simply a data abstraction layer used by the UI. So any formatting/trimming of values should really be done there.


Actipro Software Support

Posted 14 years ago by Jose Simas
Avatar
Hi,

Thanks again. That solves the problem.

Cheers,
Jose
The latest build of this product (v24.1.3) was released 3 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.