views:

568

answers:

2

I have a propertygrid with a dropdown box. In my application a user can click on a block and then the properties of that block are shown in a propertygrid. But the first time they click on a block an invalid value (0) is shown in the dropdown. How can I make sure that a valid value is shown?

Here is some code of the TypeConverter:

public class DynamicFormScreenId : Int32Converter
{

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        Database database = new Database();
        database.StoredProcedureName = "SP naam";

        int[] id = null;
        if (database.ExecuteStoredProcedure())
        {
            int totalIds = database.DataTable.Rows.Count; 
            id = new int[totalIds];

            for (int i = 0; i < totalIds; i++)
            {
                id[i] = Convert.ToInt32(database.DataTable.Rows[i][0]);
            }
        }

        return new StandardValuesCollection(id);
    }

    public override bool GetStandardValuesExclusive(
                       ITypeDescriptorContext context)
    {
        return true;
    }
}

And the property in my class:

[TypeConverter(typeof(DynamicFormScreenId)),
CategoryAttribute("Screen Settings"),
Description("The id of the screen")]
public int ScreenId
{
    get { return _screenId; }
    set { _screenId = value; }
}

SOLUTION

I set the default value of ScreenId in the constructor:

private void Constructor(string name)
{
    _controlName = name;

    // Set screenId default value
    Database database = new Database("connectionstring");
    database.StoredProcedureName = "mySP";

    if (database.ExecuteStoredProcedure())
    {
        if (database.DataTable.Rows.Count > 0)
        {
            _screenId = Convert.ToInt32(database.DataTable.Rows[0]["id"]);
        }
    }
}
+1  A: 

Have you tried the DefaultValueAttribute in System.ComponentModel?

From MSDN:

You can create a DefaultValueAttribute with any value. A member's default value is typically its initial value. A visual designer can use the default value to reset the member's value.

private bool myVal=false;

[DefaultValue(false)]
 public bool MyProperty {
    get {
       return myVal;
    }
    set {
       myVal=value;
    }
 }
Ash
I know about this attribute, but the point is, the values are stored in a database. So I can't say `DefaultValue = 1` because I don't know this value exists.
Martijn
The PropertryGrid simply shows values of an object at the time you set SelectedObject. It uses reflection to access ScreenId to get the value. Therefore you can just implement a lazy load of the value from the database within your ScreenId get {}.
Ash
I don't get it completely. In my get I can't access the StandardValuesCollection. I can't do something like this: get {return (int)SomeCollection[0];} What do you suggest/mean?
Martijn
Martijn, when the user clicks on the block, there must be some related block object instance. This is the object I would expect you pass to SelectedObject. Why can't you just load the default value from the database in the Get property of this instance? Sorry if I've completely misunderstood you, let me know and I'll stop wasting your time and delete this answer.
Ash
Thanks. I've edited my startpost with my solution
Martijn
Glad you've solved it. Any time reflection is used to create an object it normally needs your object to provide a default (parameterless) constructor. As you have found, that is the best place to initialize properties and fields.
Ash
+1  A: 

You will have to assign the object's ScreenId property value before you show it in the PropertyGrid. In effect, you have to run the dbase query twice. Once to know what value to assign to ScreenId, again in the type converter.

Hans Passant