- PR -

CheckBoxのCheckedとControlのEnabled連動

1
投稿者投稿内容
檜山
会議室デビュー日: 2006/04/13
投稿数: 15
投稿日時: 2006-06-05 23:45
Visual Studio 2005開発環境の検索ダイアログで、検索オプションの条件チェックボックスと下のコンボボックスのEnabledが連動するように、あるチェックボックスのチェック状態と連動して他のコントロールのEnabledを自動で切り替えてくれるようなユーザーコンポーネントを作ろうとしています。
最初は新規クラスライブラリプロジェクトを作ってSystem.ComponentModel.Componentを継承し、CheckBoxとControlを1セットだけ登録できるようにしてみてうまくいったのですが、欲が出てきてフォームに1個コンポーネントを貼り付けただけで複数セットを管理したいなぁ〜と思うようになりました。
そこで(ちょっと長くて申し訳ないのですが)以下のようにCollectionBaseを継承した独自コレクションと、CheckBoxとControlを1セットで管理&CheckBoxのチェック状態とControlのEnabledを連動させる独自クラスを作ってみました。
コード:
Imports System.Windows.Forms

#Region "CheckBoxとControlを1セットで管理するクラス"
Public Class EnabledControllerItem
    Private WithEvents _srcCheckBox As CheckBox
    Private _dstControl As Control

    Public Property SourceCheckBox() As CheckBox
        Get
            Return _srcCheckBox
        End Get
        Set(ByVal value As CheckBox)
            _srcCheckBox = value
        End Set
    End Property

    Public Property DestinationControl() As Control
        Get
            Return _dstControl
        End Get
        Set(ByVal value As Control)
            _dstControl = value
        End Set
    End Property

    Private Sub _srcCheckBox_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles _srcCheckBox.CheckedChanged
        If _dstControl IsNot Nothing Then
            _dstControl.Enabled = (_srcCheckBox.Checked)
        End If
    End Sub
End Class
#End Region

#Region "CheckBoxとControlの複数セットコレクション"
Public Class EnabledControllerItemCollection
    Inherits CollectionBase

    Default Public Property Item(ByVal index As Integer) As EnabledControllerItem
        Get
            Return CType(List(index), EnabledControllerItem)
        End Get
        Set(ByVal value As EnabledControllerItem)
            List(index) = value
        End Set
    End Property

    Public Function Add(ByVal item As EnabledControllerItem) As Integer
        Return List.Add(item)
    End Function
End Class
#End Region

#Region "コンポーネント本体"
Public Class EnabledController
    Inherits System.ComponentModel.Component

    Private _items As New EnabledControllerItemCollection

    Public Property Items() As EnabledControllerItemCollection
        Get
            Return _items
        End Get
        Set(ByVal value As EnabledControllerItemCollection)
            _items = value
        End Set
    End Property
End Class
#End Region



テスト用フォームにこのコンポーネントとCheckBoxとTextBoxを貼り付けてForm_Load内に直接以下のようなコードを記述したら期待通りの動作をしてくれたのですが

コード:
Dim item As New EnabledControllerItem
item.SourceCheckBox = CheckBox1
item.DestinationControl = TextBox1
EnabledController1.Items.Add(item)



デザイナ上でコレクションエディタを使ってCheckBoxとTextBoxを登録すると、InitializeComponent内に自動生成されるコードが以下のように変な状態になっていました。

コード:
        Dim EnabledControllerItem1 As EnabledControllerItem = New EnabledControllerItem
        Me.CheckBox1 = New System.Windows.Forms.CheckBox
        Me.TextBox1 = New System.Windows.Forms.TextBox

'〜Snip〜

        '
        'EnabledController1
        '
        EnabledControllerItem1.DestinationControl = Me.TextBox1
        EnabledControllerItem1.SourceCheckBox = Me.CheckBox1
New EnabledControllerItemCollection.Add(EnabledControllerItem1)    '←ここが構文エラーで実行できない

'〜Snip〜

    Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
    Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
    Friend WithEvents EnabledController1 As EnabledController




これはどこがまずいのでしょうか?
とりあえず簡単に動作確認…という段階でEnabledControllerCollectionにはItemプロパティとAddメソッドしか実装していないのですが、その辺に原因があるのか、あるいは根本的に何か間違っていますか?
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2006-06-06 15:58
引用:

とりあえず簡単に動作確認…という段階でEnabledControllerCollectionにはItemプロパティとAddメソッドしか実装していないのですが、


AddRangeを実装していないからかな?

EnabledControllerItemCollectionは、
Inherits Generic.List(Of EnabledControllerItem)
でもいいような気がします。(実装無し)
#デザイナとの絡みはわかりませんm(_ _)m

#提示コード内のItemや本体のItemsはReadOnlyにしときましょう。
檜山
会議室デビュー日: 2006/04/13
投稿数: 15
投稿日時: 2006-06-06 18:25
引用:

まどかさんの書き込み (2006-06-06 15:58) より:

AddRangeを実装していないからかな?

EnabledControllerItemCollectionは、
Inherits Generic.List(Of EnabledControllerItem)
でもいいような気がします。(実装無し)
#デザイナとの絡みはわかりませんm(_ _)m

#提示コード内のItemや本体のItemsはReadOnlyにしときましょう。



結果としては残念ながらAddRangeを実装してもInitializeComponent内では同様に頭にNewがついてしまい、うまく行きませんでした。
それから色々検索していたところDesignerSerializationVisibilityという属性を使っているものを発見し、
コード:
Public Class EnabledController
    Inherits System.ComponentModel.Component

    Private _items As New EnabledControllerItemCollection

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    Public ReadOnly Property Items() As EnabledControllerItemCollection
        Get
            Return _items
        End Get
    End Property
End Class



上記のように適用してみたら、デザイナからコレクションエディタで追加した場合にもInitializeComponent内に以下のように生成されるようになりました。(仕組みはまだよくわかっていませんが…)

コード:
        EnabledControllerItem1.DestinationControl = Me.TextBox1
        EnabledControllerItem1.SourceCheckBox = Me.CheckBox1
        Me.EnabledController1.Items.Add(EnabledControllerItem1)



EnabledControllerItemCollectionに関してはご指摘いただいた通りジェネリック対応クラスを継承するようにしたのですっきりしました。

と、ココまで試行錯誤してきて「CheckBoxとControlを複数セット管理するコンポーネント」とするより単に関連Controlを登録できる拡張CheckBoxとすればよかったな、なんてふと思ったり…
それはさておきご回答&ご助言ありがとうございました
1

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