2012-02-21 13 views
2

コンテキストヒント

は、私は小さなクラスまたは構造の非常に多くを持っています。これらのクラスの実装の詳細は重要ではありませんが、これらのクラスのそれぞれについて、WinFormsコントロールで編集できるように公開する簡単なビルトインデータ型プロパティがいくつかあります。これらは、クラスごとに完全に異なるでしょう。たとえば:

class SleepAction : IGameAction 
{ 
    public float Duration { get; set; } 
} 

class TeleportCharacterAction : IGameAction 
{ 
    public string CharacterId { get; set; 
    public string DestinationRoomId { get; set; } 
    public Vector2 DestinationPosition { get; set; } 
} 

問題は、私はこれらのオブジェクトタイプのすべてを編集することができ単一のWinFormsコントロールを持っていると思ったということです。一番上にあるすべてのクラスタイプのドロップダウンリストがあり、このドロップダウンリストからアイテムを選択すると、そのタイプのプロパティに合わせてインターフェイスが変更され、データを格納するそのタイプのインスタンスが作成されます。

最初は、TabControlオブジェクトをクラスごとに1つずつタブを非表示にして、これらの各インターフェイスを手作業で作成することを検討していました。しかし、クラスの数が急激に増加したので、おそらく属性とリフレクションを使用して、他の解決策に目を向けています。私はどのように始めるのか分かりません。

私が考えていることは、今あるようなもの:私は必要があると思います。もちろん、

class SleepAction : IGameAction 
{ 
    [FieldLabel("Duration")] 
    [FieldType("NumericSpinner")] 
    public float Duration { get; set; } 
} 

class TeleportCharacterAction : IGameAction 
{ 
    [FieldLabel("Character")] 
    [FieldType("CharacterList")] 
    public string CharacterId { get; set; 

    [FieldLabel("Room")] 
    [FieldType("RoomList")] 
    public string DestinationRoomId { get; set; } 

    [FieldLabel("Position")] 
    [FieldType("VectorPicker")] 
    public Vector2 DestinationPosition { get; set; } 
} 

class ActionEditorControl : UserControl 
{ 
    void ChangeEditorMode(Type type) 
    { 
     // Clear all GUI interface 
     // Create object of type Type with default constructor 
     // Use Type metadata to generate new GUI interface 
     // Databind new interface to object properties 
    } 

    object GetObject() 
    { 
     // Return current object 
    } 
} 

そして、私は必要なメタデータを追加するための属性を使用することができ、私のモデルオブジェクトに

これらの属性をどのように解釈するかを教えてください。今私の実際の質問のために。

固有の質問

  1. うこの作品?
  2. 私が見落としているこの問題を解決するためのより良い方法がありますか?
  3. インターフェイスのコントロールの配置やレイアウトを処理するにはどうすればよいですか?
  4. 最後に、カスタム属性を使用したことはありません。私を始めるための良い例がありますか?

答えて

2

はい、これはうまくいくはずです。エンティティに基づいて動的検索ダイアログを生成するのに似たようなものを構築しました。

カスタム属性では、フォームに表示されるプロパティを識別できます。フォームは、これらのプロパティのコントロールを生成し、データバインディングを使用してコントロールをオブジェクトのプロパティに戻します。

TableLayoutPanelは、生成されたコントロールのレイアウトに役立ちます。 1つの列にラベルオブジェクトを格納し、2番目の列にコントロール(テキストボックスなど)を格納できます。列をもっと必要とする場合は、これらのいくつかのセット。

foreach (var property in searchObjectType.GetProperties()) 
{ 
    var labelAttrib = (FieldLabelAttribute)property.GetCustomAttributes(typeof(FieldLabelAttribute), false).FirstOrDefault(); 
    var typeAttrib = (FieldTypeAttribute)property.GetCustomAttributes(typeof(FieldTypeAttribute), false).FirstOrDefault(); 
} 

表パネル:

をあなたが必要と知ったら属性

での作業あなたはタイプを持っているので、あなたはあなたの特別な属性の各プロパティを検索することができます

コントロールを構築するには、どのようなコントロールを構築するのかを理解してください(これはOrderプロパティを持つ属性を持つことを前提としていますので、コントロールをグリッドに配置します。この例では、5つのカラム、ラベル、コントロール、スペーサー、ラベル、コントロール)であることに基づいています。

if (type == typeof(string)) 
{ 
    generatedControl = new Textbox(); 
    generatedControl.DataBindings.Add("Text", myObject, property.Name); 
} 

そして(これはあなたがラベルコントロールを作成したと仮定し)、テーブルにコントロールを追加します。

pnlLayout.Controls.Add(label, (myAttrib.Order % 2 * 3), myAttrib.Order/2); 

pnlLayout.Controls.Add(generatedControl, (myAttrib.Order % 2 * 3) + 1, myAttrib.Order/2); 
+0

ありがとう、あなたはそれを釘付け!実際にはかなりシンプルに見えますが、もっと複雑になることを期待していました。 –

1

説明している内容は、PropertyGridとよく似ています。

+0

それは良い点です、私は私の質問からいくつかの情報を残している可能性があることを実感します。私は最初にプロパティグリッドを使うことを考えましたが、本当にここで欲しいのは、ラベル/テキストボックス/リスト/大きなコントロールを持つ、フォームのような一般的なコンピュータユーザーにとってより使い慣れた外観にすることです。プロパティグリッドには、このシナリオでは回避したい "プログラマ"の感覚と全体的な凝縮した外観があります。 –

+0

十分に公正。その場合、クイップの答えはかなりよく見えます。必要になったときに、カスタム構築されたUIをプラグインできるメカニズムを提供するべきでしょう。私は、属性に基づいてUIを生成するユーザーコントロールによって実装され、クラス固有のユーザーコントロールによって実装できるIEditorインターフェイスを定義します。ファクトリは正しい実装を構築することができます。 –