3

I have two property in my class: MyCountry & MyCity. I set this class to sourceobject of a property grid. I want load cities i combo when select a country. for example I have 2 Country data:

Country1
Country2

And For Country1, I have (city data)

City11
City12
City13

And For Country2, I have (city data)

city21
City22
City23

When I change select country item in propertygrid, I want load cities of it in city item. this mean, when select Country1, display City11,City12,City13 in City item and when select Country2 Display City21,Cityy22,City23 in City Item.

How can I It ?

my class is :

public class KeywordProperties
{
    [TypeConverter(typeof(CountryLocationConvertor))]
    public string MyCountry { get; set; }
    [TypeConverter(typeof(CityLocationConvertor))]
    public string MyCity { get; set; }
}

and I use below class for load countries data for display in combo :

public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {            
        HumanRoles Db = new HumanRoles();
        List<LocationsFieldSet> Items = new List<LocationsFieldSet>();
        Items = Db.LoadLocations(0);
        string[] LocationItems = new string[Items.Count];
        int count = 0;
        foreach (LocationsFieldSet Item in Items)
        {
            LocationItems[count] = Item.Title;
            count++;
        }
        return new StandardValuesCollection(LocationItems);
    }

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

1 回答 1

1

The ITypeDescriptorContext interface provides a property called Instance which lets you access the object to which the type descriptor request is connected.

You can use this property to determine the current value of the MyCountry property the user selected. Depending on the value you can load the cities for this country.

Furthermore, in the setter of the MyCountry property I check whether or not the new value is different from the old one and if this is the case I reset the MyCity property (to not get an invalid combination of country and city).

Here is a small code sample. For the sake of simplicity I only use one type converter for both properties.

public class KeywordProperties
{    
  public KeywordProperties()
  {
    MyCountry = "Country1";
  }

  private string myCountry;
  [TypeConverter(typeof(ObjectNameConverter))]
  public string MyCountry
  {
    get { return myCountry; }
    set 
    {
      if (value != myCountry)
        MyCity = "";

      myCountry = value; 
    }
  }

  private string myCity;
  [TypeConverter(typeof(ObjectNameConverter))]
  public string MyCity
  {
    get { return myCity; }
    set { myCity = value; }
  }   
}

public class ObjectNameConverter : StringConverter
{
  public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
  {
    return true;
  }

  public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
  {
    KeywordProperties myKeywordProps = context.Instance as KeywordProperties;

    if (context.PropertyDescriptor.Name == "MyCountry")
    {
      List<string> listOfCountries = new List<string>();
      listOfCountries.Add("Country1");
      listOfCountries.Add("Country2");        

      return new StandardValuesCollection(listOfCountries);
    }      

    List<string> listOfCities = new List<string>();
    if (myKeywordProps.MyCountry == "Country1")
    {
      listOfCities.Add("City11");
      listOfCities.Add("City12");
      listOfCities.Add("City13");
    }
    else
    {
      listOfCities.Add("City21");
      listOfCities.Add("City22");
      listOfCities.Add("City23");
    }

    return new StandardValuesCollection(listOfCities);
  }
}

In the example above there is one side effect I do not like. Setting the MyCountry property leads to settting also the MyCity property.

To workaround this side effect you could also use the PropertyValueChanged event of the PropertyGrid to handle invalid country/city selections.

private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
  if (e.ChangedItem.Label == "MyCountry")
  {
    if(e.ChangedItem.Value != e.OldValue)
      m.MyCity = "";
  }
}

If you use this event, just repalce the code in the setter of the MyCountry property with:

myCountry = value; 
于 2012-10-03T17:23:51.313 回答