19


「Browsable」属性を条件付きにする方法はありますか?それを適用するプロパティは、プロパティページに表示される場合と表示されない場合がありますか?
ありがとう :)

4

6 に答える 6

11

これがあなたの状況に当てはまるかどうかはわかりませんが、以下の関数を呼び出すことで、実行時に「閲覧可能」装飾を調整できます。

/// <summary>
/// Set the Browsable property.
/// NOTE: Be sure to decorate the property with [Browsable(true)]
/// </summary>
/// <param name="PropertyName">Name of the variable</param>
/// <param name="bIsBrowsable">Browsable Value</param>
private void setBrowsableProperty(string strPropertyName, bool bIsBrowsable)
{
    // Get the Descriptor's Properties
    PropertyDescriptor theDescriptor = TypeDescriptor.GetProperties(this.GetType())[strPropertyName];

    // Get the Descriptor's "Browsable" Attribute
    BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
    FieldInfo isBrowsable = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

    // Set the Descriptor's "Browsable" Attribute
    isBrowsable.SetValue(theDescriptorBrowsableAttribute, bIsBrowsable);
}
于 2013-11-19T03:04:00.020 に答える
8

簡単な方法はありません。

ICustomTypeDescriptorを実装することで、これを解決できる可能性があります。これは、 ICustomTypeDescriptorの実装に関する優れた記事です。

または、独自のControlDesignerをクラスに関連付け、PreFilterPropertiesメソッドをオーバーライドして、プロパティグリッドに表示されるプロパティを追加または削除することもできます。

プロパティグリッドから特定のプロパティを削除します。

于 2011-01-14T11:31:23.913 に答える
6

これを行うには、カスタムタイプモデルを提供します。最も単純なTypeDescriptorレベルでは、から派生したタイプのカスタムを提供し、指定さExpandableObjectConverterれたプロパティを気まぐれで含める/除外することができますが、これPropertyGridはプロパティページで使用される場合にのみ機能します。より複雑なアプローチは、ICustomTypeDescriptor/を使用することですTypeDescriptionProvider。これは、次のような内部で機能します。DataGridView

于 2011-01-14T11:31:08.373 に答える
2

上記の@neoikonの回答を改善し、コメントで言及されているGaneshの例外を回避するために、ジェネリックを使用してタイプを取得するバージョンを次に示します。

    /// <summary>
    /// Set the Browsable property.
    /// NOTE: Be sure to decorate the property with [Browsable(true)]
    /// </summary>
    /// <param name="PropertyName">Name of the variable</param>
    /// <param name="bIsBrowsable">Browsable Value</param>
    private void SetBrowsableProperty<T>(string strPropertyName, bool bIsBrowsable)
    {
        // Get the Descriptor's Properties
        PropertyDescriptor theDescriptor = TypeDescriptor.GetProperties(typeof(T))[strPropertyName];

        // Get the Descriptor's "Browsable" Attribute
        BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
        FieldInfo isBrowsable = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

        // Set the Descriptor's "Browsable" Attribute
        isBrowsable.SetValue(theDescriptorBrowsableAttribute, bIsBrowsable);
    }

次に、インスタンスを取得するバージョンを追加することもできます。

    /// <summary>
    /// Set the Browsable property.
    /// NOTE: Be sure to decorate the property with [Browsable(true)]
    /// </summary>
    /// <param name="obj">An instance of the object whose property should be modified.</param>
    /// <param name="PropertyName">Name of the variable</param>
    /// <param name="bIsBrowsable">Browsable Value</param>
    private void SetBrowsableProperty<T>(T obj, string strPropertyName, bool bIsBrowsable)
    {
        SetBrowsableProperty<T>(strPropertyName, bIsBrowsable);
    }

使用法:

    class Foo
    {
        [Browsable(false)]
        public string Bar { get; set; }
    }
    void Example()
    {
        SetBrowsableProperty<Foo>("Bar", true);
        Foo foo = new Foo();
        SetBrowsableProperty(foo, "Bar", false);
    }
于 2017-12-15T16:35:03.667 に答える
2

John Cummingsのソリューションは基本的には機能しましたが、Genericsの導入により、次の2つの問題が発生しました(これは非常に賢明でした)。

1-SetBrowsableProperty<T>(T obj, string strPropertyName, bool bIsBrowsable)コレクションがパラメーターobjとして渡されると、バージョンは失敗します。これは、TがIEnumerableの実装(リスト、配列など)であり、実際に意図されたコレクションのタイプではないためです。

2-プリミティブ型の受け渡しも可能ですが、この場合は無意味であり、ほとんどの場合失敗します。

完全な改訂ソリューション:

したがって、これらの問題に取り組み、私のために働いた改訂されたソリューションがあります:(メソッドと変数の名前を少し変更しました)

まず、Browsable属性値を変更する主な仕事を行う実際のメソッド:

/// <summary>
/// Sets the Browsable attribute value of a property of a non premitive type.
/// NOTE: The class property must be decorated with [Browsable(...)] attribute.
/// </summary>
/// <param name="type">The type that contains the property, of which the Browsable attribute value needs to be changed</param>
/// <param name="propertyName">Name of the type property, of which the Browsable attribute value needs to be changed</param>
/// <param name="isBrowsable">The new Browsable value</param>
public static void SetBrowsableAttributeOfAProperty(Type type, string propertyName, bool isBrowsable)
{
    //Validate type - disallow primitive types (this will eliminate problem-2 as mentioned above)
    if (type.IsEnum || BuiltInTypes.Contains(type))
        throw new Exception($"The type '{type.Name}' is not supported");

    var objPropertyInfo = TypeDescriptor.GetProperties(type);

    // Get the Descriptor's Properties
    PropertyDescriptor theDescriptor = objPropertyInfo[propertyName];

    if (theDescriptor == null)
        throw new Exception($"The property '{propertyName}' is not found in the Type '{type}'");

    // Get the Descriptor's "Browsable" Attribute
    BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
    FieldInfo browsablility = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

    // Set the Descriptor's "Browsable" Attribute
    browsablility.SetValue(theDescriptorBrowsableAttribute, isBrowsable);
}

現在、JohnCummingsのソリューションで提案されているバリアントは次の<T>とおりです。

public static void SetBrowsableAttributeOfAProperty<T>(string propertyName, bool isBrowsable)
{
    SetBrowsableAttributeOfAProperty(typeof(T), propertyName, isBrowsable);
}

今問題がなかった過負荷はありません。1ですが、次の変更で処理できるようになりました。

/// <summary>
/// Sets the Browsable attribute value of a property of a non premitive type.
/// NOTE: The class property must be decorated with [Browsable(...)] attribute.
/// </summary>
/// <param name="obj">An instance of the type that contains the property, of which the Browsable attribute value needs to be changed.</param>
/// <param name="propertyName">Name of the type property, of which the Browsable attribute value needs to be changed</param>
/// <param name="isBrowsable">Browsable Value</param>
public static void SetBrowsableAttributeOfAProperty<T>(T obj, string propertyName, bool isBrowsable)
{
    if (typeof(T).GetInterface("IEnumerable") != null && typeof(T) != typeof(string))   //String type needs to be filtered out as String also implements IEnumerable<char> but its not a normal collection rather a primitive type
    {
        //Get the element type of the IEnumerable collection
        Type objType = obj.GetType().GetGenericArguments()?.FirstOrDefault();       //when T is a collection that implements IEnumerable except Array
        if (objType == null) objType = obj.GetType().GetElementType();              //when T is an Array

        SetBrowsableAttributeOfAProperty(objType, propertyName, isBrowsable);
    }
    else
        SetBrowsableAttributeOfAProperty(typeof(T), propertyName, isBrowsable);

これは、すべてのC#システム組み込み(プリミティブ)タイプを取得するためのユーティリティ関数です。

    public static List<Type> BuiltInTypes
        {
            get
            {
                if (builtInTypes == null)                
                    builtInTypes = Enum.GetValues(typeof(TypeCode)).Cast<TypeCode>().Select(t => Type.GetType("System." + Enum.GetName(typeof(TypeCode), t)))
                                   .ToList();
    
                return builtInTypes;
            }
        }

使用法:

 class Foo
{
    [Browsable(false)]
    public string Bar { get; set; }
}
void Example()
{
    SetBrowsableAttributeOfAProperty<Foo>("Bar", true);     //works
    
    Foo foo = new Foo();
    SetBrowsableAttributeOfAProperty(foo, "Bar", false);    //works

    List<Foo> foos = new List<Foo> { foo, new Foo { Bar = "item2" } };
    SetBrowsableAttributeOfAProperty(foos, "Bar", true);    //works now, whereas it would crash with an exception in John Cummings's solution
}
于 2019-05-30T10:49:20.247 に答える
0

IntelliSenseで表示または非表示になっている特定のメンバーを宣言し、コンパイル時に非表示にする必要があるすべてのメンバーを一度変更できるようにする方法を探して、これに遭遇しました。それがあなたが探していたものかどうかはわかりませんが、私の質問に対する答えを見つけました...共有するのに害はないと考えました。

条件付きコンパイルシンボル(プロジェクトプロパティの[ビルド]タブにあります)IS_VIS(特定のメンバーを表示する場合はtrue、非表示にする場合はfalse)を設定してから、次のようにします。

#if IS_VIS
    public const System.ComponentModel.EditorBrowsableState isVis =
        ComponentModel.EditorBrowsableState.Always;
#else
    public const System.ComponentModel.EditorBrowsableState isVis =
        ComponentModel.EditorBrowsableState.Never;
#endif

次に、属性でisVis変数を参照します。

[EditorBrowsable(isVis)]
public string myMethod...

私はこれをVBで行い、これは急いでc#に変換されました。何かがうまくいかない場合は、私に知らせてください。

于 2012-10-25T21:52:29.177 に答える