tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル実行時に選択決定されるForm上のPublic メソッド
記事No5940
投稿日: 2007/07/30(Mon) 14:36
投稿者ひでと
お世話になります。
Form1上のButton1をクリックしたとき開くFormを、Form1上のTextBox1の値によって、
Form2,Form3のように選択して、開く処理を行っています。

Public Class Form1
    Dim fom As New Form

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Select Case TextBox1.Text
            Case "0" : fom = Form2
            Case "1" : fom = Form3
        End Select
        fom.ShowDialog()
    End Sub
End Class

Form1上の別のButton(Button2)を作成し、そのButtonをクリックして、
Form2またはForm3の新規に作った、Button_Click()を実行させたいのです。

Public Class Form2'Form3も同じ処理です
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Buttun_Click()
    End Sub
    Public Sub Buttun_Click()
        '処理
    End Sub
End Class

Public Class Form1
    Dim fom As New Form

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Select Case TextBox1.Text
            Case "0" : fom = Form2
            Case "1" : fom = Form3
        End Select
        fom.ShowDialog()
    End Sub

    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        fom.Buttun_Click() 'ここができない
    End Sub
End Class
このとき、上記の fom.Buttun_Click() がコンパイルできません。
どのようにしたら良いのでしょうか?
よろしくお願いします。

 

[ツリー表示へ]
タイトルRe: 実行時に選択決定されるForm上のPublic メソッド
記事No5966
投稿日: 2007/07/31(Tue) 13:10
投稿者るしぇ
『継承【inheritance】』についてはご理解いただけてますでしょうか?
Form2 および Form3 のコードは先頭のほうに
>    Inherits System.Windows.Forms.Form
と書かれていると思います。これにより、継承元である
System.Windows.Forms.Form クラスの ShowDialog メソッドが
コーディングなしで Form2 および Form3 で使えます。
また、
>    Dim fom As New Form
>    fom = Form2
>    fom = Form3
のように基底クラス(継承元)の変数に格納して操作できます。
このとき、fom を利用して呼び出せるのは System.Windows.Forms.Form
クラスのプロパティ・メソッドのみで、そのままでは Form2 および Form3
で定義された関数を呼ぶことはできません。

>    fom.Buttun_Click() 'ここができない
この場合、Buttun_Click() がコーディングされているのは
System.Windows.Forms.Form クラスではなく、Form2 クラスおよび
Form3 クラスです。当然、コンパイルできません。

解決法としては、
案1. Buttun_Click() がコーディングされた基底クラスを作って
Form2 および Form3 が継承する。

案2.共通のインターフェース(Interface)を Form2 および Form3 に実装する。

案3.共通処理にしない。
        Select Case TextBox1.Text
            Case "0" : Form2.Buttun_Click()
            Case "1" : Form3.Buttun_Click()
        End Select
# ま、このままだと TextBox1.Text の値を途中で変更されると不都合が
# 起こりますが。。。それは別の問題なので。

[ツリー表示へ]
タイトルRe^2: 実行時に選択決定されるForm上のPublic メソッド
記事No5979
投稿日: 2007/08/01(Wed) 10:15
投稿者ひでと
昨日留守にしてゆりましてお礼できませんでした。ありがとうございます。

> >    fom.Buttun_Click() 'ここができない
> この場合、Buttun_Click() がコーディングされているのは
> System.Windows.Forms.Form クラスではなく、Form2 クラスおよび
> Form3 クラスです。当然、コンパイルできません。
ここまでは理解できます。
>
> 解決法としては、
> 案1. Buttun_Click() がコーディングされた基底クラスを作って
> Form2 および Form3 が継承する。
>
> 案2.共通のインターフェース(Interface)を Form2 および Form3 に実装する。
>
> 案3.共通処理にしない。
>         Select Case TextBox1.Text
>             Case "0" : Form2.Buttun_Click()
>             Case "1" : Form3.Buttun_Click()
>         End Select
>  # ま、このままだと TextBox1.Text の値を途中で変更されると不都合が
>  # 起こりますが。。。それは別の問題なので。
案3ですが、実際は60の別のFormを呼び出さないといけない為、できるだけ避けたいと考えています。

第1案ですが、正直良く理解できておりません。
Public Class myForm
    Public Sub Button_Click()
    End Sub
End Class
のように新しいクラスを作り、Form2,Form3でそれをInheritsする
Public Class Form2
    Inherits myForm
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Buttun_Click()
    End Sub
    Public Sub Buttun_Click()
        '処理
    End Sub
End Class
ということでしょうか?
この場合 Inherits myForm でコンパイルエラーがでます。
また、
    Dim fom As New Form
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Select Case TextBox1.Text
            Case "0" : fom = Form2
            Case "1" : fom = Form3
        End Select
        fom.ShowDialog()
    End Sub

    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        fom.Buttun_Click() 'ここができない
    End Sub
End Class
の中のfom.Buttun_Click() はできないと思います。
もう少し アドバイスをお願いします。

[ツリー表示へ]
タイトル追伸です
記事No5980
投稿日: 2007/08/01(Wed) 10:19
投稿者ひでと
実際はForm2,Form3とはかなり違った内容のものです。
また、Buttun_Clickの処理もそれぞれで異なった処理をしています

[ツリー表示へ]
タイトルRe^3: 実行時に選択決定されるForm上のPublic メソッド
記事No5982
投稿日: 2007/08/01(Wed) 10:44
投稿者ひでと
> 第1案ですが、正直良く理解できておりません。
> Public Class myForm
>     Public Sub Button_Click()
>     End Sub
> End Class
> のように新しいクラスを作り、Form2,Form3でそれをInheritsする
> Public Class Form2
>     Inherits myForm
>     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
>         Buttun_Click()
>     End Sub
>     Public Sub Buttun_Click()
>         '処理
>     End Sub
> End Class
> ということでしょうか?
> この場合 Inherits myForm でコンパイルエラーがでます。
> また、
>     Dim fom As New Form
>
>     Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
>         fom.Buttun_Click() 'ここができない
>     End Sub
> End Class
> の中のfom.Buttun_Click() はできないと思います。
Dim fom As Object にして 2番目の疑問は解決いたしました。
1番目の「Inherits myForm でコンパイルエラーがでます」にアドバイス
お願いします。

[ツリー表示へ]
タイトル単純にこうすればいいんですね
記事No5983
投稿日: 2007/08/01(Wed) 11:55
投稿者ひでと
fom をForm型でなくObjectとして宣言する

Public Class Form1
    Dim fom As Object
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Select Case TextBox1.Text
            Case "0" : fom = Form2
            Case "1" : fom = Form3
        End Select
        fom.ShowDialog()
    End Sub

    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        fom.Buttun_Click()
    End Sub
End Class

Public Class Form2
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Buttun_Click()
    End Sub
    Public Sub Buttun_Click()
        '処理
    End Sub
End Class
脆弱な処理なのかもしれませんが、これでいいわけですね。
目が覚めました。申し訳ありませんでした。

[ツリー表示へ]
タイトルRe: 単純にこうすればいいんですね
記事No5985
投稿日: 2007/08/01(Wed) 15:59
投稿者KG
いまさらかもしれませんが、

fom.Button1.PerformClick()

などでもクリックイベントにハンドルされているプロシージャを
コールすることができますよ。

もちろんButton1が参照できる状態じゃないとダメですけども。

#既知のことでしたら申し訳ありません。

[ツリー表示へ]
タイトルRe: 単純にこうすればいいんですね
記事No5987
投稿日: 2007/08/01(Wed) 19:09
投稿者ビケ
一生懸命頑張っている様なので、私から余計なお世話をさせて頂きます。
この場合、遅延バインディング(fom をForm型でなくObjectとして宣言)を選択するべきではありません。何故なら、

1.Visual Studioの入力支援機能、メンバ一覧が表示されない
 →正確な型を指定した場合は、その型のメンバ一覧が表示されますが、Object型では、Object型が持つメンバ一覧しか表示されません。(メンバ一覧=オブジェクト(クラス)名を入力したあと「.」を入力すると自動的にメンバの一覧が表示される機能)

2.実行時にしかそのメソッドが存在するかわからない
 →例えば、Form2にButtun_Clickメソッドがあって、Form3にButtun_Clickメソッドを入れ忘れたとします。この場合、ビルドする事は可能ですが、実行後、Form3のButtun_Clickメソッドを呼び出そうとした時に初めて、そんなメソッド無いよとエラーになります。つまり、コーディングミスに気づくのは、実行して見て初めてわかるという事になります。作業効率の低下とミスを見逃す確立を上げる事になります。

上記等のリスクを覚悟した上で、それでも遅延バインディングでしか解決方法を選べないというのであれば、それはそれで現時点で的確な選択かもしれません。しかし、そうでないなら避けるべき選択案です。

この場合の適切と思われる選択案は、「案2.共通のインターフェース(Interface)を Form2 および Form3 に実装する。」です。

話は変わりますが、
>Select Case TextBox1.Text
>    Case "0" : fom = Form2
>    Case "1" : fom = Form3
>End Select
>fom.ShowDialog()

では、正しく動きませんよね?Form2とForm3はどこで、Newされるのでしょうか?また、ShowDialogすると、ボタン2はクリック出来ないと思いますが・・。説明の為にはしおったという事でしょうか?

また、この場合、ボタンのPerformClickメソッドは呼ぶべきではありません。PerformClickメソッドを呼び出すには、ボタンを公開しなければならず、クラスの特徴とも言うべきカプセル化の意味を半減させる事になるからです。ひでとさんのForm2、Form3のコーディングは、適切です。

以上、参考になれば幸いです。

[ツリー表示へ]
タイトルRe^2: 単純にこうすればいいんですね
記事No5995
投稿日: 2007/08/02(Thu) 15:41
投稿者ひでと
ありがとうございます。
> 一生懸命頑張っている様なので、私から余計なお世話をさせて頂きます。
> この場合、遅延バインディング(fom をForm型でなくObjectとして宣言)を選択するべきではありません。何故なら、
>
> 1.Visual Studioの入力支援機能、メンバ一覧が表示されない
>  →正確な型を指定した場合は、その型のメンバ一覧が表示されますが、Object型では、Object型が持つメンバ一覧しか表示されません。(メンバ一覧=オブジェクト(クラス)名を入力したあと「.」を入力すると自動的にメンバの一覧が表示される機能)
>
> 2.実行時にしかそのメソッドが存在するかわからない
>  →例えば、Form2にButtun_Clickメソッドがあって、Form3にButtun_Clickメソッドを入れ忘れたとします。この場合、ビルドする事は可能ですが、実行後、Form3のButtun_Clickメソッドを呼び出そうとした時に初めて、そんなメソッド無いよとエラーになります。つまり、コーディングミスに気づくのは、実行して見て初めてわかるという事になります。作業効率の低下とミスを見逃す確立を上げる事になります。
>
> 上記等のリスクを覚悟した上で、それでも遅延バインディングでしか解決方法を選べないというのであれば、それはそれで現時点で的確な選択かもしれません。しかし、そうでないなら避けるべき選択案です。

耳の痛いところですが、現状の私のレベルではこれが精一杯というところでした。
確かに、別の人が見たら顔をしかめますよね。
今製作しているのは、私の会社(零細の三ちゃん経営)用のプログラムで、
曲がりなりにもプログラムできるのは私一人しかいないんです。
それで、まあ自分だけ理解できれば...ということでした。

>
> この場合の適切と思われる選択案は、「案2.共通のインターフェース(Interface)を Form2 および Form3 に実装する。」です。
Interface についても見たのですが、全く解らなかったのです。
教えていただくには、私のレベルが低すぎると思い、手を出せませんでした。

>
> 話は変わりますが、
> >Select Case TextBox1.Text
> >    Case "0" : fom = Form2
> >    Case "1" : fom = Form3
> >End Select
> >fom.ShowDialog()
>
> では、正しく動きませんよね?Form2とForm3はどこで、Newされるのでしょうか?また、ShowDialogすると、ボタン2はクリック出来ないと思いますが・・。説明の為にはしおったという事でしょうか?

かなり大きなプログラムになってしまったので、あるていどはしょっていますが
クラスの宣言部分で Dim fom しています。
また、Form2とForm3はクラスを作ったわけではなく、Formを挿入して自動でできたものです。
Form2.vbになっているので、Newしなくても呼びだせると思いますが、
間違って理解しているでしょうか?

>
> また、この場合、ボタンのPerformClickメソッドは呼ぶべきではありません。PerformClickメソッドを呼び出すには、ボタンを公開しなければならず、クラスの特徴とも言うべきカプセル化の意味を半減させる事になるからです。ひでとさんのForm2、Form3のコーディングは、適切です。
>
> 以上、参考になれば幸いです。
ありがとうございます。あたって砕けろの気持ちで試行錯誤しながら作っています。
また、変なことをお聞きすることがあると思いますが、これからもよろしくお願いします。

[ツリー表示へ]
タイトルRe^3: 単純にこうすればいいんですね
記事No5998
投稿日: 2007/08/02(Thu) 16:48
投稿者ピケ
せっかくなので、インターフェースを使用した場合のソースをのせておきます。
あえて説明はしませんが、お暇な時にでも解析して下さい。

Public Class Form1
    Inherits System.Windows.Forms.Form

  Private m_Form As Form = Nothing

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

        Select Case TextBox1.Text
            Case "0"
                Me.m_Form = New Form2
            Case "1"
                Me.m_Form = New Form3
        End Select
        Me.m_Form.Show()

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        CType(Me.m_Form, IForm).Buttun_Click()

    End Sub

End Class

Public Class Form2    'Form3も同じ
    Inherits System.Windows.Forms.Form : Implements IForm

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

        Me.Buttun_Click()

    End Sub

    Public Sub Buttun_Click() Implements IForm.Buttun_Click

        MessageBox.Show("Form2")

    End Sub

End Class

Public Interface IForm

    Sub Buttun_Click()

End Interface

[ツリー表示へ]
タイトルRe^4: 単純にこうすればいいんですね
記事No6005
投稿日: 2007/08/03(Fri) 11:28
投稿者ひでと
ありがとうございます。
> せっかくなので、インターフェースを使用した場合のソースをのせておきます。
> あえて説明はしませんが、お暇な時にでも解析して下さい。
努力いたします。

[ツリー表示へ]