2

カスタム コントロールを作成する最初の試みとして、Gridview Web コントロールを拡張しています。

拡張機能の一部として、コントロール内のグリッド列ヘッダーのローカライズをカプセル化しています。特に、この機能を有効にするためにいくつかのプロパティを公開しています。

bool AutoLocalizeColumnHeaders - 機能を有効にします

string HeaderResourceFile - ヘッダー テキストを取得する厳密に型指定されたリソース クラスを識別します

OnRowDataBound ハンドラーをオーバーライドし、Reflection を使用して適切な ResourceManager を取得して、ヘッダー テキストを設定しています。これはすべてうまく機能していますが、名前を手動で入力するのではなく、ユーザーが選択できるように、使用可能な厳密に型指定されたリソース クラスのリストを [プロパティ] ウィンドウに表示したいと考えています。

利用可能なクラスを表示するドロップダウンを表示するための TypeConverter を作成しましたが、表示する利用可能なクラス名のリストを取得する方法がわかりません。

私はかなり長い間試みてきましたが、成功せず、正気を失いつつあります。リフレクションを使用してこれを達成する方法があるに違いないと思いますか?

4

3 に答える 3

1

私は今解決策を見つけたと思います。

Page_Loadイベント内から以下を実行すると、Resourceクラス名が得られました。

String[] resourceClassNames = (from type in assembly.GetTypes()
   where type.IsClass && type.Namespace.Equals("Resources")
   select type.Name).ToArray();

そのため、TypeConverterのGetResourceFileNames(ITypeDescriptorContext context)関数内から、コンテキストパラメーターを使用して正しいアセンブリを取得することで、同様のことができると思いました。残念ながら、カスタムコントロールのアセンブリまたはSystem.Webアセンブリしか取得できなかったようです。

そのため、代わりに、EditValueルーチンにIServiceProviderが渡されるUITypeEditorを作成しました。これから、ITypeDiscoveryServiceのインスタンスを作成することができました。これを使用して、正しいアセンブリからすべての型を取得しました。

public override object EditValue(ITypeDescriptorContext context, 
                                 IServiceProvider provider, object value)
{
    // Check if all the expected parameters are here
    if (context == null || context.Instance == null || provider == null)
    {
        // returning with the received value
        return base.EditValue(context, provider, value);
    }

    // Create the Discovery Service which will find all of the available classes
    ITypeDiscoveryService discoveryService = (ITypeDiscoveryService)provider.GetService(typeof(ITypeDiscoveryService));
    // This service will handle the DropDown functionality in the Property Grid
    _wfes = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

    // Create the DropDown control for displaying in the Properties Grid
    System.Windows.Forms.ListBox selectionControl = new System.Windows.Forms.ListBox();
    // Attach an eventhandler to close the list after an item has been selected
    selectionControl.SelectedIndexChanged += new EventHandler(selectionControl_SelectedIndexChanged);
    // Get all of the available types
    ICollection colTypes = discoveryService.GetTypes(typeof(object), true);
    // Enumerate the types and add the strongly typed
    // resource class names to the selectionControl
    foreach (Type t in colTypes)
    {
        if (t.IsClass && t.Namespace.Equals("Resources"))
        {
            selectionControl.Items.Add(t.Name);
        }
    }
    if (selectionControl.Items.Count == 0)
    {
        selectionControl.Items.Add("No Resources found");
    }
    // Display the UI editor combo
    _wfes.DropDownControl(selectionControl);

    // Return the new property value from the UI editor combo
    if (selectionControl.SelectedItem != null)
    {
        return selectionControl.SelectedItem.ToString();
    }
    else
    {
        return base.EditValue(context, provider, value);
    }
}

void selectionControl_SelectedIndexChanged(object sender, EventArgs e)
{
    _wfes.CloseDropDown();
}

これはうまくいくようですが、LinQを使用して必要な型を取得するためのよりスタイリッシュな方法があると思いますが、LinQを調べ始めたばかりであり、コレクションに対してクエリを実行するときに正しい構文を取得できないようです。前の例のように配列。

誰かがこれを行うLinQ構文、または実際にすべてを達成するためのより良い方法を提案できるなら、それは大歓迎です。

于 2008-12-05T19:41:30.087 に答える
0

面白いアイデア。あなたのプロパティは現在文字列として設定されていると思いますか?プロパティを列挙型として設定してから、強く型付けされたリソースクラスを使用して列挙型を作成するのではないかと思います。プロパティウィンドウにそれらを表示するのに十分賢いのでしょうか。コードビハインドに表示するのに十分スマートで、プロパティウィンドウにロードできなかった理由がわかりません。

于 2008-12-05T18:25:31.597 に答える
0

以前に投稿したソリューションでは、LinQ を使用して次のことを行う方法を見つけたいと考えていました。

    // Get all of the available types
    System.Collections.ICollection colTypes = discoveryService.GetTypes(typeof(object), true);
    // Enumerate the types and add the strongly typed resource class names to the selectionControl
    foreach (Type t in colTypes)
    {
        if (t.IsClass && t.Namespace.Equals("Resources"))
        {
            selectionControl.Items.Add(t.Name);
        }
    }

これはビジネスを行うようです:

    // Get all of the available class names from the Resources namespace
    var resourceClassNames = from Type t in discoveryService.GetTypes(typeof(object), true)
                        where t.IsClass && t.Namespace.Equals("Resources")
                        select t.Name;

    selectionControl.Items.AddRange(resourceClassNames.ToArray());

それは確かにずっときれいに見え、コードの基準を満たすものをチェックして、利用可能なすべてのタイプをループするわけではないので、パフォーマンスが向上すると思います。より効率的な方法ではありますが、LinQが私のためにこれを行っていると思いますか?

于 2008-12-07T14:56:54.637 に答える