Ereditato controllo / Visibile Enabled Proprietà Valore sempre vero: PropertyGrid
-
30-09-2019 - |
Domanda
Ho creato un WinForms personalizzati ambiente di hosting. Che ha una serie di strumenti e di un PropertyGrid.
I comandi visualizzato nella casella degli strumenti sono ereditate dai controlli WinForm esistenti.
DropDownList Fonte:
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
}
Ho implementato ICustomTypeDescriptor
per filtrare le proprietà che io non voglio mostrare nel PropertyGrid
.
Problema:
Sono di fronte problema durante la serializzazione valori delle proprietà Enabled
& Visible
che sono ereditati dalla classe System.Windows.Forms.Control
.
WriteProperties Method (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;
}
}
}
}
Problema # 1:. Il metodo ShouldSerializeValue
per la proprietà Enabled
& Visible
restituisce sempre false
Problema # 2:. Anche se mi salta il metodo ShouldSerializeValue
controllare il metodo GetValue
del PropertyDescriptor
restituisce sempre True
attuale Soluzione:
Per aggirare il problema che ho attualmente composto le proprietà Enabled
& Visible
nascosti utilizzando il BrowsableAttribute
, e ha creato altre due proprietà booleane e utilizzato il DisplayNameAttribute
di cambiare il nome visualizzato in essere Enable
& Visible
.
Ma per questa soluzione devo scrivere questi frammenti in ogni controllo.
Mi manca qualcosa o fare qualcosa di sbagliato? Perché la Enabled
& proprietà Visible
non cambiano?
Soluzione
Troverete una lunga discussione su questo problema qui . (Link morto, non riesce a trovare uno nuovo)
MSDN pagina aldo rende questo notare:
La classe InheritedPropertyDescriptor modifica il valore predefinito di un proprietà, in modo che il valore predefinito è il valore corrente dell'oggetto istanziazione. Questo perché il proprietà viene ereditata da un altro esempio. I definisce progettista reimpostare il valore della proprietà come impostandolo al valore che è stato impostato dalla classe ereditata. Questo valore può diversa dal valore predefinito memorizzato nei metadati.
valore di ritorno di ShouldSerializeValue si basa sulla differenza tra il valore attuale e il valore di default quindi penso che questo è direttamente correlata al vostro problema.
Spero che questo vi aiuterà a capire ciò che accade nel proprio contesto.