継承されたコントロール可視/有効プロパティ値は常に真:PropertyGrid
-
30-09-2019 - |
質問
カスタムWinformsホスティング環境を作成しました。ツールボックスとプロパティグリッドがあります。
ツールボックスに表示されるコントロールは、既存の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
, 、および他の2つのブールプロパティを作成して使用しました DisplayNameAttribute
ディスプレイ名を変更します Enable
& Visible
.
しかし、この回避策のために、私はこれらのスニペットをあらゆるコントロールに書く必要があります。
私は何かが足りないのですか、それとも何か間違ったことをしていますか?なぜそうなのか Enabled
& Visible
プロパティは変更されませんか?
解決
この問題について長い議論を見つけるでしょう ここ. 。 (デッドリンク、新しいものが見つかりません)
これ MSDNページ アルドはこの発言をします:
継承されたPropertyDescriptorクラスは、プロパティのデフォルト値を変更するため、デフォルト値はオブジェクトインスタンス化の現在の値になります。これは、プロパティが別のインスタンスから継承されているためです。設計者は、プロパティ値をリセットすることを、継承されたクラスによって設定された値に設定すると定義します。この値は、メタデータに保存されているデフォルト値とは異なる場合があります。
Shouldserializevalueの返品値は、現在の値とデフォルト値の違いに基づいているため、これは問題に直接関連していると思います。
これがあなた自身の文脈で何が起こるかを理解するのに役立つことを願っています。