「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
子コントロールを持つFormやカスタム コントロールの子コントロールを生成する処理を、
コンストラクタに実装した場合、実行時の表示が「不正になる」現象に対する対処方法等を纏めている。
この問題は、
で発生する。
デザイン時に使用できる値は、実行時に使用できる値と異なる。
対策としては、InitLayout?イベント・ハンドラをオーバ ライドして
カスタム コントロールの初期化処理を同梱するという方法が有用である。
また、Designプロパティを使用してデザイン時と実行時を判別できる。
この結果が、*.Designer.cs(vb)に出力される
VisualStudio?デザイナの仕様であるため、
子コントロールの二重登録のような問題が起きてしまう。
Windows Formsでは、デザイン専用コードを実装する必要が無いため、
ASP.NET Web Formsのケースより簡単にデザイン時と実行時の表示を一致させることが出来るが、
製品レベルの作り込みで、通常、ユーザ・プログラムでここまでの実装は行わない方が無難であると考える。
コンストラクタに実装した処理を、ロード イベントに移動する。
GetDesignTimeHtml?メソッドからVisual Studioデザイナに表示するHTMLを返すことで対応する。
/// <summary>コンストラクタ</summary>
/// <summary>コンストラクタでプロジェクトなどでの標準スタイルを適用する。</summary>
public WebCustRadioButtonList() {
  // 初期設定のプロパティ値を設定する。
  // ※デザインタイム・プロパティのほうが優先される。
  // WebCustRadioButtonListの初期化(データバインド)
  string[] itemlist = { "選択項目1", "選択項目2", "選択項目3" };
  this.DataSource = itemlist;
  this.DataBind();
  // 横方向にオプションボタンを並べて表示する。
  this.RepeatDirection = RepeatDirection.Horizontal;
}カスタムのRadioButtonList?コントロールのタグ内に、
子コントロール(ListItem?)のコレクションのタグが出力される。<my_wcc:WebCustRadioButtonList ID="WebCustRadioButtonList1" runat="server" Width="340px"> <asp:ListItem Value="選択項目1">選択項目1</asp:ListItem> <asp:ListItem Value="選択項目2">選択項目2</asp:ListItem> <asp:ListItem Value="選択項目3">選択項目3</asp:ListItem> </my_wcc:WebCustRadioButtonList>
この実装の状態で、Visual Studioデザイナでコントロールのサイズを変更したところ、
Visual Studioデザイナ上での表示が下記のような、意図せぬ表示となる問題が発生する。
<my_wcc:WebCustRadioButtonList ID="WebCustRadioButtonList1" runat="server" Width="340px"> <asp:ListItem Value="選択項目1">選択項目1</asp:ListItem> <asp:ListItem Value="選択項目2">選択項目2</asp:ListItem> <asp:ListItem Value="選択項目3">選択項目3</asp:ListItem> <asp:ListItem Value="選択項目1">選択項目1</asp:ListItem> <asp:ListItem Value="選択項目2">選択項目2</asp:ListItem> <asp:ListItem Value="選択項目3">選択項目3</asp:ListItem> </my_wcc:WebCustRadioButtonList>
これは、Visual Studioデザイナ上でコンストラクタが2回実行され、
DataSource?にListItem?が2回追加されたためである。
/// <summary>WebCustRadioButtonListのVisual Studioデザインサポートを実装する</summary>
internal class WebCustRadioButtonListDesigner : ControlDesigner {
  /// <summary>メンバ変数にWebCustRadioButtonListを保持</summary>
  protected WebCustRadioButtonList wcrbl;
  /// <summary>初期化</summary>
  public override void Initialize(IComponent component) {
    if (component is WebCustRadioButtonList) {
      base.Initialize(component);
      this.wcrbl = (WebCustRadioButtonList)component;
    }
  }
  /// <summary>Visual Studioデザイナに表示するHTMLを返す。</summary>
  public override string GetDesignTimeHtml() {
    try {
      // 非常に単純なコードであるため、
      // スタイル関係のプロパティ設定、子コントロールのインスタンス数のプロパティ設定を反映しない。
      string ret = ""
      + "<table>"
      + "  <tr>"
      + "    <td>"
      + "      <input type=\"radio\" value=\"選択項目1\" />"
      + "      <label >選択項目1</label>"
      + "    </td>"
      + "    <td>"
      + "      <input type=\"radio\" value=\"選択項目2\" />"
      + "      <label>選択項目2</label>"
      + "    </td>"
      + "    <td>"
      + "      <input type=\"radio\" value=\"選択項目3\" />"
      + "      <label >選択項目3</label>"
      + "    </td>"
      + "  </tr>"
      + "</table>";
      return ret;
    }
    catch (Exception ex) {
      // エラーの場合
      return String
        .Concat("<h3>Error</h3>Stack Trace:<br>", ex.StackTrace);
    }
  }
}/// <summary>System.Web.UI.RadioButtonListのカスタム・コントロール</summary>
[Designer("Ctrl.WebCustRadioButtonListDesigner"),
ToolboxData("<{0}:WebCustRadioButtonList runat=server></{0}:WebCustRadioButtonList>")]
public class WebCustRadioButtonList : RadioButtonList一致させるには複雑な実装が必要になる。
Tags: :.NET開発, :UIサブシステム, :Windows Forms, :ASP.NET Web Forms