2014年5月13日火曜日

VB コントロールの親子関係

先ず、最初に断っておきます。  親子関係って、今話題の DNA 鑑定 とかじゃなくって ... お分かりですよね。
プログラミングのお話です。
暫く前に、msdn フォーラムで、.Net Framework に関するお問い合わせがあって、
そこで、投稿していました。  その辺のお話を纏めたいと思います。
コントロールの親子関係と、あるプロパティの継承についてです。


ご自分で作るソフトのインターフェース つまり 画面上のコントロールには親子関係が成立しています。
親と子は密接な関係で、連携して、時には、独立して、動いていますね。

ご質問のリンクは掲載しませんが、趣旨は こんな感じ です。
  コントロールクラスの .visible プロパティ に関する msdn の以下の説明が間違っているのでは?
      コントロールとそのすべての子コントロールが表示されているかどうかを示す値を取得または設定します。
      http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.visible(v=vs.110).aspx

簡素に書き流してある この説明文ですが、 実際、経験を積まれた方には、身に染み付いている分、違和感はない筈です。
というのは、このプロパティを利用するのは、主に、設定時が多いからでしょう。
   感覚的に理解してしまっているというか ... 。
しかし、取得に限って見れば、ご質問者さんの疑問が分かりますね。
親が True で、子が False なら、子は表示されない訳で、 文面から受け取る内容とは少し差異が生じていますね。
子は子で、独立した値を保持していますから。
また、親が False の場合、 子が True でも False でも、子は表示されず、
ここで、子の値をどう設定しても、表示には反映されません。 取得値も False 。
親が True に変わると既設定の子の設定が戻って来ます。
ここでも、文面から受け取る内容とは少し差異が生じていますね。
実際の挙動とは違っていますから。   取得と設定を、一緒に説明してしまったので、変な文章なのでしょうね。 
     実は、以前、画面を作っていて、 この手の問題で痛い目にあっています。
     .visible の値で判断して、画面推移を操作しようとしても、思う様に行かないのです。
     この原因は、親子関係にあります。 継承する場合と、独立する場合が、混在するからですね。
フォーラムでも書いたのですが、Visible という言葉に原因があります。
  visible という単語を良く考えて見て下さい。  見る事ができる 可視化 という意味ですね。
  決して、状態を表す言葉(見えるかどうか)では、ありません
  確かに、その親 や その子 の設定状況によって、実態は表さないので、この表現は、誤解を招き易い とは思いますが
設定では その可能性を、取得では その状態を、と、 異なった事象を対象にいているので、分かり難いのでしょうか ね。  
  う~ん、書いていて頭がこんがらがって来ます。  お読みになって、表現が、合っていますか? 不安です。


では、混乱してしまわない為に、サンプルを動かしてみましょう。
親子の継承関係を見て行きます。

大きさの異なる GroupBox を3つ 重ね合わせて、親子関係を作ります。
この外側に、GroupBox の visible を指定する CheckBox を3つ と、実際に変更・操作する Button をひとつ、
状況を把握する為に表示する Label をひとつ、 配置した Form を作ります。



コードはこれです。
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ResetComponent()    ' 各コントロールの設定を調整

        Me.CheckBox1.Checked = True
        Me.CheckBox2.Checked = True
        Me.CheckBox3.Checked = True

        Me.Label1.Text = "Please Check" + Chr(13) + " and Click Button1"

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        ' Set Visible Value
        Me.GroupBox1.Visible = Me.CheckBox1.Checked
        Me.GroupBox2.Visible = Me.CheckBox2.Checked
        Me.GroupBox3.Visible = Me.CheckBox3.Checked

        ' Show Visible Status
        Me.Label1.Text = "GroupBox Visible (Get)" + Chr(13) + _
                         "GB1 : " + IIf(Me.GroupBox1.Visible, "True", "False") + Chr(13) + _
                         "GB2 : " + IIf(Me.GroupBox2.Visible, "True", "False") + Chr(13) + _
                         "GB3 : " + IIf(Me.GroupBox3.Visible, "True", "False") + Chr(13) + _
                         Chr(13) + _
                         "GroupBox Parent" + Chr(13) + _
                         "GB1 : " + Me.GroupBox1.Parent.Name + Chr(13) + _
                         "GB2 : " + Me.GroupBox2.Parent.Name + Chr(13) + _
                         "GB3 : " + Me.GroupBox3.Parent.Name
    End Sub

    Private Sub ResetComponent()
        'Setting Compoent

        Me.Text = "Test  Parent and Child"
        Me.Size = New System.Drawing.Size(500, 310)

        Me.GroupBox1.Controls.Clear()
        Me.GroupBox1.Controls.Add(Me.GroupBox2)
        Me.GroupBox1.Size = New System.Drawing.Size(300, 230)
        Me.GroupBox1.Location = New System.Drawing.Point(22, 22)
        Me.GroupBox1.BackColor = System.Drawing.Color.White

        Me.GroupBox2.Controls.Clear()
        Me.GroupBox2.Controls.Add(Me.GroupBox3)
        Me.GroupBox2.Size = New System.Drawing.Size(240, 190)
        Me.GroupBox2.Location = New System.Drawing.Point(22, 30)
        Me.GroupBox2.BackColor = System.Drawing.Color.Silver

        Me.GroupBox3.Controls.Clear()
        Me.GroupBox3.Size = New System.Drawing.Size(180, 150)
        Me.GroupBox3.Location = New System.Drawing.Point(32, 30)
        Me.GroupBox3.BackColor = System.Drawing.Color.Gray

        Me.CheckBox1.Location = New System.Drawing.Point(330, 70)
        Me.CheckBox1.Text = "GB1.Visible (Set)"

        Me.CheckBox2.Location = New System.Drawing.Point(330, 90)
        Me.CheckBox2.Text = "GB2.Visible (Set)"

        Me.CheckBox3.Location = New System.Drawing.Point(330, 110)
        Me.CheckBox3.Text = "GB3.Visible (Set)"

        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(335, 140)

        Me.Button1.Location = New System.Drawing.Point(350, 30)

    End Sub

End Class


実行して戴ければ、一目瞭然。
Form1 > GroupBox1 >  GroupBox2 >  GroupBox3 という親子孫の関係が分かります。
基本的には、上から下へと継承されて行きますが、実は、下は下で独立した値を保持しています。 (取得は不可。)
visible プロパティの変化 と 画面表示 が、決して、単純ではない関係である事がお分かり戴けると思います。
飽く迄も、visible プロパティの値は、可能性なのです。
それだけが、単独で表示を掌っている訳ではありません。  ややこしいですね。



[2014/04/19] 操作を間違いまして、書き掛け状態で、公開していました。 ご覧になった方へ、失礼しました
[2014/05/13] やっと、コードを公開用に手直しする時間が取れました

0 件のコメント:

コメントを投稿