التحكم الموروثة مرئية/قيمة الخاصية الممكّن دائمًا صحيح: PropertyGrid
-
30-09-2019 - |
سؤال
لقد أنشأت بيئة استضافة مخصصة. التي لديها صندوق أدوات و propertyGrid.
يتم توريث عناصر التحكم المعروضة في صندوق الأدوات من عناصر تحكم Winform الموجودة.
مصدر القفل:
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
}
لقد نفذت ICustomTypeDescriptor
لتصفية الخصائص التي لا أرغب في إظهارها في PropertyGrid
.
مشكلة:
أواجه مشكلة أثناء تسلسل القيم Enabled
& Visible
الخصائص الموروثة من System.Windows.Forms.Control
صف دراسي.
طريقة WriteProperties (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;
}
}
}
}
المشكلة رقم 1: ال ShouldSerializeValue
طريقة ل Enabled
& Visible
الملكية دائما تعيد خطأ.
المشكلة رقم 2: حتى لو تخطيت ShouldSerializeValue
الطريقة تحقق من GetValue
طريقة PropertyDescriptor
يعود دائما True
.
الحل البديل الحالي:كحل بديل ، قمت حاليًا بعمل Enabled
& Visible
الخصائص المخفية باستخدام BrowsableAttribute
, ، وخلق اثنين من الخصائص المنطقية الأخرى واستخدمت DisplayNameAttribute
لتغيير اسم العرض الخاص بهم ليكون Enable
& Visible
.
لكن بالنسبة لهذا الحل ، يجب أن أكتب هذه المقتطفات في كل عنصر تحكم.
هل أفتقد شيئًا أو أفعل أي شيء خاطئ؟ لماذا Enabled
& Visible
الممتلكات لا تتغير؟
المحلول
ستجد مناقشة طويلة حول هذه المسألة هنا. (Dead Link ، لا يمكن العثور على واحدة جديدة)
هذه صفحة MSDN ألدو يدلي هذه الملاحظة:
تعمل فئة ClortedPropertyDescriptor على تعديل القيمة الافتراضية للخاصية ، بحيث تكون القيمة الافتراضية هي القيمة الحالية في إنشاء مثيل للكائن. وذلك لأن الخاصية ورثت من مثيل آخر. يحدد المصمم إعادة تعيين قيمة الخاصية على أنها ضبطها على القيمة التي تم تحديدها بواسطة الفئة الموروثة. قد تختلف هذه القيمة عن القيمة الافتراضية المخزنة في البيانات الوصفية.
تعتمد قيمة إرجاع usserializeValue على الفرق بين القيمة الحالية والقيمة الافتراضية لذلك أعتقد أن هذا مرتبط مباشرة بمشكلتك.
آمل أن يساعدك هذا في معرفة ما يحدث في سياقك الخاص.