2017-04-12 56 views
0

我正在使用屬性網格來顯示對象屬性。必須根據條件顯示動態屬性。我需要顯示列表項作爲下拉列表。 所以我寫了一些必要的類。 (請考慮這個列表也是動態的)。屬性網格類型'System.String'的對象不能轉換爲'x'類型

我有一個自定義屬性網格,你可以看到:

public class myPropertyGrid : PropertyGrid 
     { 
     private System.ComponentModel.Container components = null; 

     public myPropertyGrid() 
     {   
      InitializeComponent();   
     } 

     protected override void Dispose(bool disposing) 
     { 
      if(disposing) 
      { 
       if(components != null) 
       { 
        components.Dispose(); 
       } 
      } 
      base.Dispose(disposing); 
     } 

     #region Codice generato da Progettazione componenti 
     /// <summary> 
     /// Metodo necessario per il supporto della finestra di progettazione. Non modificare 
     /// il contenuto del metodo con l'editor di codice. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      // 
      // UserControl1 
      // 
      this.Name = "myPropertyGrid";   

     } 
     #endregion  

     protected override PropertyTab CreatePropertyTab(Type tabType) 
     {   
      myTab t = new myTab(); 
      return t; 
     }   
    } 

    public class myTab : PropertyTab 
    { 
     public myTab() 
     {    
     } 

     // get the properties of the selected component 
     public override System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, System.Attribute[] attributes) 
     { 
      PropertyDescriptorCollection properties; 
      if(attributes!=null) 
       properties=TypeDescriptor.GetProperties(component,attributes);    
      else 
       properties=TypeDescriptor.GetProperties(component);  

      //Componet must implement the ICUSTOMCLASS interface. 
      ICustomClass bclass=(ICustomClass)component;  

      //The new array of properties, based on the PublicProperties properties of "model" 
      PropertyDescriptor[] arrProp = new PropertyDescriptor[bclass.PublicProperties.Count];          

      for (int i=0;i<bclass.PublicProperties.Count;i++) 
      { 
       //Find the properties in the array of the propertis which neme is in the PubliCProperties 
       PropertyDescriptor prop=properties.Find(bclass.PublicProperties[i].Name,true); 
       //Build a new properties 
       arrProp[i] = TypeDescriptor.CreateProperty(prop.ComponentType, prop, new CategoryAttribute("جزئیات")); 
      } 
      return new PropertyDescriptorCollection(arrProp); 
     } 

     public override System.ComponentModel.PropertyDescriptorCollection GetProperties(object component) 
     {      
      return this.GetProperties(component,null); 
     } 

     // PropertyTab Name 
     public override string TabName 
     { 
      get 
      { 
       return "Properties"; 
      } 
     } 

     //Image of the property tab (return a blank 16x16 Bitmap) 
     public override System.Drawing.Bitmap Bitmap 
     { 
      get 
      {    
       return new Bitmap(16,16);; 
      } 
     } 
    } 

我有一個名爲對propertyList類,這個類是從屬性網格添加屬性的屬性網格和移除屬性。

​​

而對於自定義屬性的類

public class CustomProperty 
    { 
     private string sName = string.Empty; 
     private bool bReadOnly = false; 
     private bool bVisible = true; 
     private object objValue = null; 
     private object tag = null; 
     private string displayName = string.Empty; 
     public CustomProperty(object tag, string sName, object value, Type type, bool bReadOnly, bool bVisible) 
     { 
      this.tag = tag; 
      this.sName = sName; 
      this.objValue = value; 
      this.type = type; 
      this.bReadOnly = bReadOnly; 
      this.bVisible = bVisible; 
     } 

     public CustomProperty(object tag, string displayName, string sName, object value, Type type, bool bReadOnly, bool bVisible) 
      :this(tag,sName,value,type,bReadOnly,bVisible) 
     { 
      this.displayName = displayName; 
     } 

     private Type type; 

     public Type Type 
     { 
      get { return type; } 
     } 

     public bool ReadOnly 
     { 
      get 
      { 
       return bReadOnly; 
      } 
     } 

     public string Name 
     { 
      get 
      { 
       return sName; 
      } 
      set 
      { 
       sName = value; 
      } 
     } 

     public bool Visible 
     { 
      get 
      { 
       return bVisible; 
      } 
     } 

     public object Value 
     { 
      get 
      { 
       return objValue; 
      } 
      set 
      { 
       objValue = value; 

      } 
     } 
     public object Tag 
     { 
      get 
      { 
       return tag; 
      } 
      set 
      { 
       tag = value; 
      } 
     } 

     public string DisplayName 
     { 
      get 
      { 
       return displayName; 
      } 
      set 
      { 
       displayName = value; 
      } 
     } 
} 

我想補充一點,從動態列表中創建組合框,爲這個目的,我必須寫這樣的代碼:

[TypeConverter(typeof(VersionConvertor))] 
[Editor(typeof(VersionTypeEditor), typeof(UITypeEditor))] 
public class VersionClass 
{ 
    public VersionClass() 
    { 

    } 
} 

public class VersionConvertor : TypeConverter 
{ 

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

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

} 
public class VersionTypeEditor : UITypeEditor 
{ 

    private IWindowsFormsEditorService _editorService; 
    private ListBox lb; 
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
    { 
     // drop down mode (we'll host a listbox in the drop down) 
     return UITypeEditorEditStyle.DropDown; 
    } 

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
    { 
     _editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); 

     // use a list box 
     lb = new ListBox(); 
     lb.SelectionMode = SelectionMode.One; 
     lb.SelectedValueChanged += OnListBoxSelectedValueChanged; 
     lb.DisplayMember = "Name"; 


     List<string> listItem = new List<string>(); 
     listItem.Add("a"); // assume that these items are added dynamically 
     listItem.Add("b"); 
     foreach (string item in listItem) 
     { 
      lb.Items.Add(item); 
     } 

     lb.SelectedItem = listItem[0]; 
     lb.ValueMember = listItem[0]; 

     _editorService.DropDownControl(lb); 
     if (lb.SelectedItem == null) // no selection, return the passed-in value as is 
      return value; 

     return lb.SelectedItem; 
    } 
    private void OnListBoxSelectedValueChanged(object sender, EventArgs e) 
    { 
     lb.SelectedItem = ((ListBox)(sender)).SelectedItem; 
     _editorService.CloseDropDown(); 
    } 
} 

當我點擊字母下拉列表並選擇一個項目,出現錯誤: enter image description here

enter image description here

我該如何解決這個錯誤?

回答

0

這是一個老問題,但我有一個答案。

ComboBox中的選項是字符串;您明確將其添加到lb.ItemsVersionTypeEditor.EditValue()。從我收集到的問題來看,必須將Alphabet屬性設置爲VersionClass的一個實例。這是你的錯誤的來源:表單期望的是一個VersionClass,而ComboBox正在傳遞一個字符串。

你需要的是將字符串轉換爲VersionClass。您已經設置了一個VersionConverter類,並使用TypeConverterAttribute將其應用於VersionClass。現在您需要通過覆蓋TypeConverter.CanConvertFrom()TypeConverter.ConvertFrom()方法來添加轉換的邏輯。這裏有一個例子(未經測試):

public class VersionConverter : TypeConverter 
{ 
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context) 
    { 
     return true; 
    } 

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

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     if (type == typeof(string)) 
     { 
      return true; 
     } 
     return base.CanConvertFrom(context, sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     if (value is string) 
     { 
      // conversion logic goes here 
      return convertedVersionClass; 
     } 
     return base.ConvertFrom(context, culture, value); 
    } 
} 

希望能回答你的基本問題。不過,我也注意到,您明確在VersionTypeEditor.EditValue()中使用lb.Items.Add()添加選項。您可以通過在VersionConverter中重寫更多方法來更輕鬆地動態填充ComboBox。具體來說,您想覆蓋TypeConverter.ConvertTo()以獲取VersionClass並返回將出現在ComboBox中的字符串表示形式,然後重寫TypeConverter.GetStandardValues()以返回包含要在ComboBox中出現的對象的TypeConverter.StandardValuesCollection。

this MDSN page上詳細討論了我在這裏陳述的許多內容,包括TypeConverter.ConvertTo()TypeConverter.GetStandardValues()

相關問題