投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/1/13 18:24:14
> 書いていただきましたコードに置き換えたところ
> 違う箇所がエラーになってしまいました。
そんなコード、私は提示していませんよ? 混ぜちゃダメです。


> Public Sub Button1_Click
普通に作ると、イベントハンドラーは Private Sub になるはずなのですが、
これは意図的に Public に変更されていますね。

Public にするということは、その処理を別のクラスから呼び出すことを意味しますが、
イベント ハンドラーを外部から直接呼び出すのは、あまりよくないコーディング手法なので
本来は Private のままで設計した方が望ましいです。


> なるほど!初期値になってしまうんですね。どうりで空白なわけです。

下記のようなコードを実行すると、Button1 を押すたびに、
新しい Form2 が表示される事象を確認できると思います。

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim f As New Form2()
        f.Text = "Form2 - " & Now.ToString()
        f.Show(Me)
    End Sub
End Class



> Public Class BarcodeReaderの下に
>     ''' <summary>受信データ</summary>
>     Private Shared g_Data As String = ""

え……Shared 付きにしているのですか!?

インスタンス メンバーではなく、共有メンバーになっているということは、
BarcodeReader クラスのインスタンスがいくつあったとしても、
g_Data は一つ分しか存在しないことを意味します。


たとえば、TextBox というクラスのことを考えてみてください。
Form1 に貼った TextBox1, TextBox2 と
Form2 に貼った TextBox1, TextBox2 は、それぞれ独立しており、
それぞれの Text プロパティは、別々の文字列を扱えますよね。
これはつまり、TextBox クラスのインスタンスが 4 つ存在している状態にあたりますし、
Text プロパティも、それぞれのインスタンスごとに存在しているということになります。

それに対して、Shared で宣言された g_Data の場合、
 Dim x As New BarcodeReader()
 Dim y As New BarcodeReader()
のように、複数のインスタンスがあったとしても、g_Data 変数は一つしか存在できません。

それぞれのインスタンスごとに別々の g_Data として管理したいのであれば、Shared を外して
 Private g_Data As String = ""
とするべきですし、逆に、Shared として単一データとして管理したいのであれば、
BarcodeReader クラスが複数のインスタンスを持てないよう、
いわゆる「シングルトン」なクラスとして設計されるべきでしょう。

何故、このような設計にしてあるのか、作成者にコードの意図を聞いてみたいところですが…
質問の本筋からは離れてしまうので、とりあえず横に置いておきます。


さて現状、g_Data は Private となっているようですから、別のクラスから
 BarcodeReader.g_Data = "新しい値"
のようにして書き換えられるようにはなっておらず、
BarcodeReader クラスの内部からしか編集できない仕様ですよね。

ではその g_Data は、BarcodeReader クラス内の
どのタイミングで書き換えられるようにしたいのでしょうか?


呼び出し元で New したときに初期値をセットして、
それ以降は編集しないパターンの場合は、こう書きます。

Public Class Form2
    Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim human1 As New BarcodeReader(TextBox1.Text)
        human1.DataReceived()
    End Sub
End Class

Public Class BarcodeReader
    ''' <summary>受信データ</summary> 
    Private Shared g_Data As String = ""
    Public Sub DataReceived()
        MsgBox(g_Data)
    End Sub
    Public Sub New()
    End Sub
    Public Sub New(s As String)
        g_Data = s
    End Sub
End Class



New したときには、g_Data に対して特に何もせず、
DataReceived を呼び出したときに書き換えたいパターンでは、こう書けます。

Public Class Form2
    Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim human1 As New BarcodeReader()
        human1.DataReceived(TextBox1.Text)
    End Sub
End Class

Public Class BarcodeReader
    ''' <summary>受信データ</summary> 
    Private Shared g_Data As String = ""
    Public Sub DataReceived(s As String)
        g_Data = s
        MsgBox(g_Data)
    End Sub
End Class



固定値を渡すのではなく、コールバックさせたい場合はこうです。
ほぼ、先程の再掲ですが。

Public Class Form2
    Private WithEvents human As New BarcodeReader()
    Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        human.DataReceived()
    End Sub
    Private Sub human_RequireData(sender As Object, e As BarcodeReader.RequireEventArgs) Handles human.RequireData
        e.Data = TextBox1.Text
    End Sub
End Class

Public Class BarcodeReader
    ''' <summary>受信データ</summary> 
    Private Shared g_Data As String = ""

    ''' <summary>データ受信用イベント</summary> 
    Public Event RequireData As EventHandler(Of RequireEventArgs)

    ''' <summary>イベントを通じてデータを受信する</summary> 
    Private Sub ReceiveText()
        Dim e As New RequireEventArgs()
        RaiseEvent RequireData(Me, e)
        g_Data = e.Data
    End Sub

    Public Sub DataReceived()
        ReceiveText()
        MsgBox(g_Data)
    End Sub

    ''' <summary>データ受信イベント引数</summary> 
    Public Class RequireEventArgs
        Inherits EventArgs
        Public Property Data As String
    End Class
End Class