2

カスタムコントロールを作成しようとしているときに、Visual Studio(2005/2008)エディターと組み合わせたSystem.Windows.Forms.TextFormatFlags列挙型で問題が発生しました。この問題の理由は、この列挙型にゼロ値にマップされる複数のメンバーがあるという事実に起因しているようです。これらのメンバー(GlyphOverhangPadding、Left、Default、Top)のいずれかを選択すると、エディターはプロパティを次のように設定します。

this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.GlyphOverhangPadding;

コードは期待どおりにコンパイルされます。ただし、エディターのプロパティグリッドからゼロ以外のメンバー(「右」など)を選択すると、次のようになります。

this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right;

明らかに、これはコンパイルされません。ゼロ以外のメンバーを複数選択すると(UITypeEditorを使用して、たとえば「Right | Bottom」)、次のようになります。

this.customControl.TextFormatFlags = ((System.Windows.Forms.TextFormatFlags)((System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right | System.Windows.Forms.TextFormatFlags.Left, Default, Top, Bottom)));

ご覧のとおり、エディターは4つのゼロ値メンバーのうち3つを選択したアイテムに追加します。

この問題を再現したい場合:

  • Visual Studio 2005/2008(Windowsフォームアプリケーション)で新しいプロジェクトを作成する
  • プロジェクトにカスタムコントロールを追加します。
  • 新しいクラスにプライベートフィールドとパブリックプロパティを追加します。

    private TextFormatFlags tff = TextFormatFlags.Default;

    public TextFormatFlags TFFProperty {get {return this.tff; } set {this.tff = value; }}

  • コードをコンパイルする

  • デザイナでForm1を開き、CustomControl1を追加します
  • コードは正常にコンパイルされます
  • 次に、エディターのPropertyGridでCustomControl1のプロパティを開きます
  • 「その他」セクションの下にTFFPropertyが表示されます。
  • プロパティにはいくつかの値があり、そのほとんどにコンマが含まれています。
  • カンマを使用して値のいずれかを選択すると(「Left、Default、Top、Horizo​​ntalCenter」など)、コンパイルできないコードになります

Flags属性を使用して独自の列挙型を作成し、ゼロにマップされた複数のメンバーを追加した場合も同じことが起こります(これは、不正な形式のフラグ列挙型の一種ですか?)。これは、使用しているUITypeEditorのバグではないことを確認しました(UITypeEditorを使用しなくても同じ問題が発生します)。私はコンバーターの問題を回避しようとしましたが、これまでのところ成功していません。この問題を解決する方法について誰かが何かアイデアを持っているなら、私はそれらを聞いてうれしいです。

4

1 に答える 1

3

Reflectorを使用して名前空間のさまざまなクラスを確認しましたがSystem.ComponentModel.Design.Serialization、CodeDomシリアライザーは少しやんちゃだと思います。

列挙型はによって処理されますEnumCodeDomSerializer.Serialize。その目的は、列挙型を取得してSystem.CodeDom.CodeExpression、デザイナーファイルに表示されるものを表すオブジェクトに変換することです。

このメソッドは、式のアスペクトCodeBinaryOperatorExpressionを処理するために正しく使用されます。|ただし、個々の列挙値については、Enum.ToStringviaEnumTypeConverterを使用し、結果の文字列を式ツリーに直接貼り付けます。

Enum.ToStringはあなたが見ているものの究極の原因だと思います:

複数の列挙型メンバーが同じ基になる値を持ち、基になる値に基づいて列挙型メンバーの名前の文字列表現を取得しようとする場合、コードはメソッドが返す名前について何も想定しないでください。

確かに、のMSDNページでEnum.ToStringはコンマについては説明されていませんEnum.ToStringが、有効なC#式であるという出力に依存するのは安全ではないようです。

これがあなたのコントロールにとって何を意味するのかわかりません:

  • TextFormatFlags明らかに、ゼロフラグを複製せずに、独自の置換を定義して実行できます。
  • カスタムタイプコンバーター、おそらくに変換するものでそれをハックできるかもしれませんInstanceDescriptor。これにより、デザイナーが生成したコードに表示される内容をもう少し制御できます。
  • intデザイナーのシリアライザーに公開することもできますがTextFormatFlags、プロパティグリッドに公開することもできます

編集: のコンマ区切りリストの動作Enum.ToStringは実際に文書化されています

于 2009-12-07T20:57:00.027 に答える