- PR -

デザイナ上からユーザーコントロール内のコントロールを触れなくする方法は?

1
投稿者投稿内容
ひろめん
会議室デビュー日: 2009/01/19
投稿数: 10
投稿日時: 2009-03-10 03:18
VS2008のC#、windowsフォームアプリでコーディングをしています。
下記コードのようにユーザーコントロールのプロパティにラジオボタンの配列を持たせ、
デザイナ上で追加を行えるようにしたいと思っています。
コード:
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace RadioListControl {
    public partial class UserControl1 : UserControl {

        #region フィールド

        private RadioButton[] _items = null;

        #endregion

        #region コンストラクタ

        public UserControl1() {
            InitializeComponent();
        }

        #endregion

        #region プロパティ

        public RadioButton[] Items {
            get { return _items; }
            set { this._addItems(value); }
        }

        #endregion

        #region メソッド

        private void _addItems(RadioButton[] items) {
            if (items == null) return;

            //既にあるラジオボタンを一度クリア
            foreach (Control c in this.Controls) {
                if (typeof(RadioButton).Equals(c) == true) {
                    this.Controls.Remove(c);
                }
            }

            _items = items;

            int i = 0;
            foreach (RadioButton r in _items) {
                r.Parent = this;
                r.Top = i;
                i += 25;
            }
        }
    #endregion
    }
}


上記コードのユーザーコントロールで、デザイナ上でのコレクションエディタを使ったラジオボタンの追加はできたのですが、
デザイナ上で追加したラジオボタンをD&Dでき、D&Dするとラジオボタンの親がフォームになってしまい
ユーザーコントロールを配置しなおさない限り戻せなくなってしまいます。

デザイナで設定した直後
コード:
//InitializeComponent内のコード(抜粋)

//プロパティウィンドウからラジオボタンを追加した時
this.userControl11 = new RadioListControl.UserControl1();
this.radioButton1 = new System.Windows.Forms.RadioButton();
this.userControl11.SuspendLayout();
this.SuspendLayout();
// userControl11
this.userControl11.Controls.Add(this.radioButton1);//←ユーザーコントロールにaddされているが・・・
this.userControl11.Items = new System.Windows.Forms.RadioButton[] {this.radioButton1};
this.userControl11.Name = "userControl11";
// radioButton1
this.radioButton1.Name = "radioButton1";
this.radioButton1.Size = new System.Drawing.Size(104, 24);
// Form1
this.ClientSize = new System.Drawing.Size(368, 252);
this.Controls.Add(this.userControl11);
this.Name = "Form1";


ラジオボタンをD&Dで動かすと…
コード:
//InitializeComponent内のコード(抜粋)

//デザイナ上のラジオボタンをD&Dで移動した後
this.userControl11 = new RadioListControl.UserControl1();
this.radioButton1 = new System.Windows.Forms.RadioButton();
this.userControl11.SuspendLayout();
this.SuspendLayout();
// userControl11
this.userControl11.Name = "userControl11";
// radioButton1
this.radioButton1.Name = "radioButton1";
this.radioButton1.Size = new System.Drawing.Size(104, 24);
// Form1
this.ClientSize = new System.Drawing.Size(368, 252);
this.Controls.Add(this.radioButton1);            //←フォームにaddされるようになってしまう
this.Controls.Add(this.userControl11);
this.userControl11.Items = new System.Windows.Forms.RadioButton[] {
this.Name = "Form1";


ラジオボタンの配置はユーザーコントロール内で計算して設定するつもりですので、
ユーザーコントロールをフォームに配置した時点で、追加したラジオボタンをマウスクリック等で選択できないようにしたいのですが、
実現方法を見つけることができませんでした。

質問事項は下記の2点です。
1:ラジオボタンを、デザイナのフォーム上から触れないようにする方法。
2:1が不可能であれば、ラジオボタンをD&Dしたときに親をユーザーコントロールのまま維持する方法。

何か情報をお持ちの方は回答の程よろしくお願いします。
AlexSuns
会議室デビュー日: 2005/03/14
投稿数: 5
お住まい・勤務地: 桜島のちかく
投稿日時: 2009-03-10 10:19
2の方法になりますが、継承元をPanel等に変更するだけでいいですね
ひろめん
会議室デビュー日: 2009/01/19
投稿数: 10
投稿日時: 2009-03-10 12:55
ご返答ありがとうございます。

確かにユーザーコントロール内でのD&Dは解決しましたが、
ラジオボタンをフォームにドロップすると、やはりラジオボタンの親がフォームに移ってしまいました。
(そのあとユーザーコントロールにドロップすると戻せますが)
できればラジオボタンの管理をユーザーコントロール内のみで行いたいと考えていますので、
フォームにドロップできるという状態を何とかしたいです。

別のアプローチとして今のところ思いつくのは、現状のようにプロパティでラジオボタンの配列を公開するのではなく、
ユーザーコントロールのプロパティでは、ラジオボタンの生成に必要な情報を持つクラスのコレクションを
持つようにし、ラジオボタンは情報クラスのリストをもとに、ユーザーコントロール内で
privateで生成すればよいのかなと考えています。
この方法がスマートなのかどうかわかりませんが、他に一般的な手法をご存知の方がいらっしゃいましたら
何か情報を頂けると幸いです。
ひとまず上記の方法でうまく動くか、ためしに組んでみることにします。
セラフ
ベテラン
会議室デビュー日: 2005/12/01
投稿数: 95
お住まい・勤務地: 東北の顔の形といえば
投稿日時: 2009-03-10 12:58
OnControlAddedやOnControlRemovedなどのメソッドをオーバーライドして、
追加できないようにしたり、削除できないようにするのはどうでしょうか?
ひろめん
会議室デビュー日: 2009/01/19
投稿数: 10
投稿日時: 2009-03-11 09:52
ご返答ありがとうございます。返事が遅くなって申し訳ありません。

OnControlAddedをオーバーライドして、ラジオボタンを削除する処理のイメージは
このような感じでしょうか。
コード:
protected override void OnControlAdded(ControlEventArgs e)
{
    base.OnControlAdded(e);
    if (e.Control is RadioButton == true)
    {
        this.Controls.Remove(e.Control);
    }
}


上記コードのみでは、コレクションエディタからの追加でもラジオボタンを削除してしまいますので
その辺の区別をつける必要があるみたいですね…
プロパティウィンドウのコレクションエディタから追加しようとしているのか、
ツールボックスやフォーム上からのD&Dのように、外部から追加しようとしているのかを
判断する方法はないものでしょうか
DesignModeプロパティというものを見つけましたが、これは目的とは用途が違うみたいでした。
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2009-03-11 10:05
フォームで処理されている場合はフォームのデザイナ+(UserControl)CodeDomSerializer
で処理されているので、思われている方法は無理※だと思います。(特にAdd部分)
更に派生したUserControlでD&Dすれば問題ないと思いますが。。。。
。。それではダメ?

#※デザイナ+CodeDomSerializerから作れば可能な気がしますが。。美味しい?


[ メッセージ編集済み 編集者: indigo-x 編集日時 2009-03-11 10:08 ]
ひろめん
会議室デビュー日: 2009/01/19
投稿数: 10
投稿日時: 2009-03-12 09:26
プロパティに持たせる配列をRadioButton[]から、
ラジオボタンを生成するための情報を持ったクラスの配列に置き換え、
_AddItemsメソッド内でRadioButtonを生成することで
目的の動きを実装することができました。

しかし正直なところ、InitializeComponentで自動で吐かれるコードが
どのような仕組みで動いているかが不明なままなので、引き続き
調べてみたいと思います。
なんとなくですがクラスのシリアライズがキーポイントなのかなと感じました。

>indigo-xさん
CodeDomSerializerの情報ありがとうございます。
今回は上記方法で実装するつもりですが、
教えていただいたクラスの使い方も、追って調べてみようと思います。
1

スキルアップ/キャリアアップ(JOB@IT)