3

J'ai créé un environnement d'hébergement WinForms personnalisé. Qui a une boîte à outils et un PropertyGrid.Contrôle hérité Valeur de propriété visible/activée Toujours vrai: PropertyGrid

Les contrôles affichés dans la boîte à outils sont hérités des contrôles WinForm existants.

DropDownList Source:

public interface IPropertyFilter : ICustomTypeDescriptor 
{ 
    PropertyDescriptorCollection FilterProperties(PropertyDescriptorCollection pdc); 
    List<string> GetPropertiesToShow(); 
} 

[Serializable] 
public class DropDownList : System.Windows.Forms.ComboBox, IPropertyFilter 
{ 
    public DropDownList() 
    { 
    } 

    #region IPropertyFilter Members 

    public TypeConverter GetConverter() 
    { 
     return TypeDescriptor.GetConverter(this, true); 
    } 

    public EventDescriptorCollection GetEvents(Attribute[] attributes) 
    { 
     return TypeDescriptor.GetEvents(this, attributes, true); 
    } 

    EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents() 
    { 
     return TypeDescriptor.GetEvents(this, true); 
    } 

    public string GetComponentName() 
    { 
     return TypeDescriptor.GetComponentName(this, true); 
    } 

    public object GetPropertyOwner(PropertyDescriptor pd) 
    { 
     return this; 
    } 

    public AttributeCollection GetAttributes() 
    { 
     return TypeDescriptor.GetAttributes(this, true); 
    } 

    public PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
    { 
     PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(this, attributes, true); 
     return FilterProperties(pdc); 
    } 

    PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties() 
    { 
     PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(this, true); 
     return FilterProperties(pdc); 
    } 

    public object GetEditor(Type editorBaseType) 
    { 
     return TypeDescriptor.GetEditor(this, editorBaseType, true); 
    } 

    public PropertyDescriptor GetDefaultProperty() 
    { 
     return TypeDescriptor.GetDefaultProperty(this, true); 
    } 

    public EventDescriptor GetDefaultEvent() 
    { 
     return TypeDescriptor.GetDefaultEvent(this, true); 
    } 

    public string GetClassName() 
    { 
     return TypeDescriptor.GetClassName(this, true); 
    } 

    public PropertyDescriptorCollection FilterProperties(PropertyDescriptorCollection pdc) 
    { 
     // Filter out properties that we do not want to display in PropertyGrid 
     return ControlDesignerHelper.GetBrowsableProperties(pdc, GetPropertiesToShow()); 
    } 

    // Determines what properties of this control has to be shown in PropertyGrid 
    public List<string> GetPropertiesToShow() 
    { 
     // get a list of common properties that we want to show for all controls 
     List<string> browsableProps = ControlDesignerHelper.GetBasePropertiesToShow(); 
     // add properties that are specific to this controls 
     browsableProps.Add("Items"); 
     browsableProps.Add("AutoPostBack"); 
     browsableProps.Add("AppendDataBoundItems"); 
     browsableProps.Add("DataTextField"); 
     browsableProps.Add("DataValueField"); 
     return browsableProps; 
    } 

    #endregion 
} 

J'ai mis en ICustomTypeDescriptor pour filtrer les propriétés que je ne veux pas montrer dans le PropertyGrid.

Problème:

Je suis face à problème alors que les valeurs de sérialisation Enabled & Visible propriétés héritées de System.Windows.Forms.Control classe.

WriteProperties Méthode (BasicDesignerLoader):

private void WriteProperties(XmlDocument document, PropertyDescriptorCollection properties, object value, XmlNode parent, string elementName) 
{ 
    foreach (PropertyDescriptor prop in properties) 
    { 
     System.Diagnostics.Debug.WriteLine(prop.Name); 

     if (prop.ShouldSerializeValue(value)) 
     { 
      string compName = parent.Name; 
      XmlNode node = document.CreateElement(elementName); 
      XmlAttribute attr = document.CreateAttribute("name"); 

      attr.Value = prop.Name; 
      node.Attributes.Append(attr); 

      DesignerSerializationVisibilityAttribute visibility = (DesignerSerializationVisibilityAttribute)prop.Attributes[typeof(DesignerSerializationVisibilityAttribute)]; 

      switch (visibility.Visibility) 
      { 
       case DesignerSerializationVisibility.Visible: 
        if (!prop.IsReadOnly && WriteValue(document, prop.GetValue(value), node)) 
        { 
         parent.AppendChild(node); 
        } 

        break; 

       case DesignerSerializationVisibility.Content: 
        object propValue = prop.GetValue(value); 

        if (typeof(IList).IsAssignableFrom(prop.PropertyType)) 
        { 
         WriteCollection(document, (IList)propValue, node); 
        } 
        else 
        { 
         PropertyDescriptorCollection props = TypeDescriptor.GetProperties(propValue, propertyAttributes); 

         WriteProperties(document, props, propValue, node, elementName); 
        } 

        if (node.ChildNodes.Count > 0) 
        { 
         parent.AppendChild(node); 
        } 

        break; 

       default: 
        break; 
      } 
     } 
    } 
} 

Problème n ° 1: La méthodeShouldSerializeValue pour la Enabled & Visible propriété retourne toujours faux.

Problème n ° 2: Même si je saute la méthode ShouldSerializeValue vérifier la méthode GetValue du PropertyDescriptor retourne toujours True.

Solution actuelle: Pour contourner ce problème, je l'ai fait actuellement les Enabled & Visible propriétés cachées en utilisant la BrowsableAttribute, et a créé deux autres propriétés booléennes et a utilisé le DisplayNameAttribute de changer leur nom d'affichage pour être Enable & Visible.

Mais pour cette solution de contournement, je dois écrire ces extraits dans chaque contrôle.

Est-ce que je manque quelque chose ou si je fais quelque chose de mal? Pourquoi la propriété Enabled & Visible ne change pas?

Répondre

1

Vous trouverez une longue discussion à propos de ce numéro here. (Lien mort, ne peut pas trouver un nouveau)

Ce MSDN page aldo fait cette remarque:

La classe InheritedPropertyDescriptor modifie la valeur par défaut d'une propriété , de sorte que la valeur par défaut est la valeur actuelle à l'objet instanciation. Cela est dû au fait que la propriété est héritée d'une autre instance . Le concepteur définit en réinitialisant la valeur de propriété en la définissant à la valeur qui a été définie par la classe héritée.Cette valeur peut différer de la valeur par défaut stockée dans les métadonnées.

La valeur de retour de ShouldSerializeValue est basée sur la différence entre la valeur actuelle et la valeur par défaut, donc je pense que cela est directement lié à votre problème. J'espère que cela vous aidera à comprendre ce qui se passe dans votre propre contexte.

Questions connexes