質問

カスタム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の返品値は、現在の値とデフォルト値の違いに基づいているため、これは問題に直接関連していると思います。

これがあなた自身の文脈で何が起こるかを理解するのに役立つことを願っています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top