C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: 別フォームにデータを渡したい


(過去ログ 151 を表示中)

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■87756 / inTopicNo.1)  別フォームにデータを渡したい
  
□投稿者/ いまそかり (1回)-(2018/06/28(Thu) 11:49:57)

分類:[.NET 全般] 

いつもお世話になっております。
VB.NET初心者です。

Form1でDBから取得したデータを、Form2にあるコンボボックスに入れたいのですが、
調べるうちにどうもよく分からなくなってきたため、分かる方いましたら是非ご教授をお願いします。
その際、サンプルコードか参考となるページなどがあれば、よければ教えていただけますとありがたいです。



<開発環境>
vb2015、.NET Framework3.0

<ソースコード>
【関数の呼び出し元Form1】

Public class Form1 

	'xmlからデータを取得
	Function xmlGet(Byval a As String,Byval b As String)

		'xmlへのパスやLoadなど(省略)

		 	  ・
			  ・
			  ・
			  ・

	End Function


	'フォーム内での動き
	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

		'DBに接続するための情報をxmlから取得(※1)
		Dim id As String = xmlGet("a","b_id") 
		Dim pass As String = xmlGet("a","b_pass")

 
		'接続文字列の指定やSQL文の設定、接続、DBからレコード取得(省略)
			
					 ・
					 ・
					 ・
					 ・

	End Sub


	'ボタンクリックイベント(Form2が開く)
	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        
		Dim frm As Form2
        	frm = New Form2
        	frm.Show()  

	End Sub

End class	



【Function関数を使用したいForm2】

Public Class Form2

	'ここでDBから取得した値をコンボボックスに入れる
	Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
		
		'コンボボックスにDB内のテーブルを連結
            	'コンボボックスに表示したいデータ
   	        '実際に扱うデータをSelectValueで取得する
      	    	
	End Sub

End class


----------------------------------------------------------------------------------------


【質問】

@Form1_LoadをprivateのままでForm2で取得し、使用したい

実行:Form2で
	
	'Form1のインスタンス化
	Dim cls As New Form1
	cls.Form1_Load() 'エラー発生

エラー内容:Form1_Loadはprivateのためアクセスできない



AForm2でForm1_Loadだけを取得した場合、(※1)は正常に動作するのか

(以下では、正常に動作しなかった場合を考えました)
実行:Form2で

	'Form1のインスタンス化
	Dim cls As New Form1
	cls.xmlGet() 'エラー発生

エラー内容:変数aとbに対して引数が指定されていない
		→ aとbには引数を1つではなく複数入れたいため、配列を使用する必要がある?


-----------------------------------------------------------------------------------------


素人が作成しているため、細かい間違いが多いと思います。何卒ご容赦下さい。
ですが、大きな間違いに関してはご指摘くだされば幸いです。
以上、よろしくお願いします。

引用返信 編集キー/
■87757 / inTopicNo.2)  Re[1]: 別フォームにデータを渡したい
□投稿者/ にゃるら (25回)-(2018/06/28(Thu) 12:26:20)
No87756 (いまそかり さん) に返信
> 【質問】
>
> @Form1_LoadをprivateのままでForm2で取得し、使用したい

ある型のメンバを呼び出すのに、Reflectionが使えます。

http://smdn.jp/programming/netfx/reflection/

privateなインスタンスメンバであれば

BindingFlags.NonPublic | BindingFlags.Instance

の条件をつけることでアクセスできます。

> AForm2でForm1_Loadだけを取得した場合、(※1)は正常に動作するのか

正常の意味がよくわからないですが、呼び出そうとする処理の中に
状態や変数のライフタイムなどが関係ないようなものであれば
大丈夫じゃないでしょうか。

ちなみに余計なお世話ですけども。
「素人」というのが本当なのであれば、privateでなくpublicだけで実装されるのが無難と思いますよ。
動くプログラムを作られてからカプセル化に挑戦する方が良いと思いますよ。

引用返信 編集キー/
■87758 / inTopicNo.3)  Re[1]: 別フォームにデータを渡したい
□投稿者/ WebSurfer (1534回)-(2018/06/28(Thu) 12:28:32)
No87756 (いまそかり さん) に返信

> Form1でDBから取得したデータを、Form2にあるコンボボックスに入れたいのですが、

Form2 のコンストラクタにデータを渡すための引数を持つものを追加し、frm = New Form2 のところで
そのコンストラクタを使って frm = New Form2(データ) というようにしてはいかがですか?
引用返信 編集キー/
■87759 / inTopicNo.4)  Re[2]: 別フォームにデータを渡したい
□投稿者/ 魔界の仮面弁士 (1723回)-(2018/06/28(Thu) 12:54:11)
No87758 (WebSurfer さん) に返信
> Form2 のコンストラクタにデータを渡すための引数を持つものを追加し、frm = New Form2 のところで
> そのコンストラクタを使って frm = New Form2(データ) というようにしてはいかがですか?

この方法に一票。

ただし注意点として、
 (1) 引数付きコンストラクタだけでなく、引数なしコンストラクタもオーバーロードで残すこと。
 (2) コンストラクタ内では、最初に InitializeCompoent() を呼び出すこと。
を忘れずに。
引用返信 編集キー/
■87760 / inTopicNo.5)  Re[2]: 別フォームにデータを渡したい
□投稿者/ 774RR (613回)-(2018/06/28(Thu) 13:50:47)
提示コードはいろいろむちゃくちゃな感触がして、もっとがんばりましょう状態というか。
以下は全部重大な誤りなので要修正。

Form1 は普通自分で new しない。デザイナ側で自動的に new するコードが生成済みのはず。
自分で new Form1 するってことは今画面に出ている Form1 とは別の画面を new するってこと。
それはたぶん期待されている動作ではない。

Form1_Load はイベントハンドラなので、システムによって呼ばれる代物であって自分では呼ばない。

Form2 は Button1_Click の中の自動変数なのでいつ gc されてもおかしくない。
つまり勝手に消えちゃうかもしれないってこと。
Form1 のメンバにするとかそういう修正が必要。

引用返信 編集キー/
■87762 / inTopicNo.6)  Re[3]: 別フォームにデータを渡したい
□投稿者/ 魔界の仮面弁士 (1724回)-(2018/06/28(Thu) 14:45:07)
No87760 (774RR さん) に返信
> Form2 は Button1_Click の中の自動変数なのでいつ gc されてもおかしくない。
> つまり勝手に消えちゃうかもしれないってこと。

Show した時点で、Application.OpenForms() の管理下に入るので、
フォームを閉じない限り、勝手に消えることはないのでは…?
引用返信 編集キー/
■87764 / inTopicNo.7)  Re[2]: 別フォームにデータを渡したい
□投稿者/ いまそかり (3回)-(2018/06/28(Thu) 16:58:08)
No87757 (にゃるら さん) に返信

にゃるらさん、回答ありがとうございます。


>>@Form1_LoadをprivateのままでForm2で取得し、使用したい
> 
> ある型のメンバを呼び出すのに、Reflectionが使えます。
> 
>   http://smdn.jp/programming/netfx/reflection/
> 
> privateなインスタンスメンバであれば
> 
>   BindingFlags.NonPublic | BindingFlags.Instance
> 
> の条件をつけることでアクセスできます。


なるほどそういう方法があったんですね!
早速書いてみました。

Dim fType As Type = Form1.GetType()

        Dim f2 As New Form2()

        fType.InvokeMember("Form1_Load",
                           BindingFlags.NonPublic Or
                           BindingFlags.Instance Or
                           BindingFlags.InvokeMethod,
                           Nothing,
                           From1,
                           New Object() {Form1, f2}
                           )


参考(https://dobon.net/vb/dotnet/programing/invokenonpublicmember.html
「隠蔽されている非パブリックメンバを呼び出す」)

これで合ってますかね…?




>>AForm2でForm1_Loadだけを取得した場合、(※1)は正常に動作するのか
> 
> 正常の意味がよくわからないですが、呼び出そうとする処理の中に
> 状態や変数のライフタイムなどが関係ないようなものであれば
> 大丈夫じゃないでしょうか。
> 
> ちなみに余計なお世話ですけども。
> 「素人」というのが本当なのであれば、privateでなくpublicだけで実装されるのが無難と思いますよ。
> 動くプログラムを作られてからカプセル化に挑戦する方が良いと思いますよ。


あ、すみません「正常」という言葉は「エラーは出ないのか?」という意味で使ったので、その解釈であってます。
「素人」という言葉も「初心者」という意味合いで使っていました。
 
また、以前「基本はPublicではなくPrivateで書いたほうがいい」と授業で習った覚えがあったので、
Privateで記述していました。
でも、まずはにゃるらさんの言う通りPublicでやった方がやりやすいかもですね…。
次回からはその方法も試してみます。

引用返信 編集キー/
■87765 / inTopicNo.8)  Re[3]: 別フォームにデータを渡したい
□投稿者/ いまそかり (4回)-(2018/06/28(Thu) 18:05:42)
■No87759 (魔界の仮面弁士 さん) に返信
■No87758 (WebSurfer さん) に返信

魔界の仮面弁士さん、WebSurferさん、回答ありがとうございます。


>>Form2 のコンストラクタにデータを渡すための引数を持つものを追加し、frm = New Form2 のところで
>>そのコンストラクタを使って frm = New Form2(データ) というようにしてはいかがですか?

> ただし注意点として、
>  (1) 引数付きコンストラクタだけでなく、引数なしコンストラクタもオーバーロードで残すこと。
>  (2) コンストラクタ内では、最初に InitializeCompoent() を呼び出すこと。
> を忘れずに。



基からデータを渡すための引数を設定…思いつきませんでした。
書きやすそうだったので、上記のご意見を踏まえて書き直してみました。
※追加したコードは***で囲ってあります。



<修正後ソースコード>

【Form1】
Public class Form1 

***********************
*	
*	'Form2のコンストラクタにデータを渡すための引数を入れる変数
*	Dim df As DataSet
*
***********************



	'xmlからデータを取得
	Function xmlGet(Byval a As String,Byval b As String)

		'xmlへのパスやLoadなど(省略)

		 	  ・
			  ・
			  ・
			  ・

	End Function


	'フォーム内での動き
	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

		'DBに接続するための情報をxmlから取得
		Dim id As String = xmlGet("a","b_id") 
		Dim pass As String = xmlGet("a","b_pass")

 
		'接続文字列の指定やSQL文の設定、接続、DBからレコード取得(省略)
			
					 ・
					 ・
					 ・
					 ・

	End Sub


***********************
*
*	'ボタンクリックイベント(Form2が開く)
*	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
*       
*		Dim frm As Form2
*        	frm = New Form2(df) 
*        	frm.Show()  '(※1)
*
*	End Sub
*
***********************


End class	



【Form2】

Public Class Form2


***********************
*
*	Private df As DataSet
*
*
*	'Form2のオーバーロード(引数あり)
*	Public Sub New()
*
*        	InitializeComponent()
*
*	End Sub
*
*
*	'Form2のオーバーロード(引数あり)
*	Public Sub New(df As DataSet)
*              IntializeComponent()
*        	Me.df = df
*	End Sub
*
***********************


	'ここでDBから取得した値をコンボボックスに入れる
	Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
		

***********************
*
*	'Form1_Loadの呼び出し
*	Dim fType As Type = Form.GetType()
*
*      Dim f2 As New Form()
*
*      fType.InvokeMember("Form1_Load",
*                         BindingFlags.NonPublic Or
*                         BindingFlags.Instance Or
*                         BindingFlags.InvokeMethod,
*                         Nothing,
*                         Form1,
*                         New Object() {Form1, f2}
*                         )
*
*
*		'コンボボックスにDB内のテーブルを連結
*		'ここでdf使ってます
*
***********************

            	'コンボボックスに表示したいデータ
   	        '実際に扱うデータをSelectValueで取得する
      	    	
	End Sub

End class






上手く書くことが出来ました!
しかし、エラーもなかったので実行してみると、ソースコードの(※1)のところで
「保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」
という例外が発生してしまいます。

これも色々と調べてはみたのですが、よく分からず…。
すみませんが、引き続きご教授頂けますとありがたいです。
(タイトル違いでしたら新しいスレッド立てます)

引用返信 編集キー/
■87766 / inTopicNo.9)  Re[4]: 別フォームにデータを渡したい
□投稿者/ WebSurfer (1536回)-(2018/06/28(Thu) 19:19:43)
No87765 (いまそかり さん) に返信

> ***********************
> *
> * 'Form1_Loadの呼び出し
> * Dim fType As Type = Form.GetType()
> *
> * Dim f2 As New Form()
> *
> * fType.InvokeMember("Form1_Load",
> * BindingFlags.NonPublic Or
> * BindingFlags.Instance Or
> * BindingFlags.InvokeMethod,
> * Nothing,
> * Form1,
> * New Object() {Form1, f2}
> * )
> *
> *
> * 'コンボボックスにDB内のテーブルを連結
> * 'ここでdf使ってます
> *
> ***********************

上記は何でしょう? 意味がなさそうに見えるのですが。と言うよりこれがエラーの原因???

frm = New Form2(df) で Form2 を初期化する際に Form1 で生成した DataSet への参照を引数 df
経由で渡して、その後 Form2 の Load イベントのハンドラで、渡された DataSet の情報を元に
Form2 に配置されている ComboBox を設定するのではないのですか?

であれば、そのコードは意味不明&多分不要なのですが・・・



引用返信 編集キー/
■87769 / inTopicNo.10)  Re[3]: 別フォームにデータを渡したい
□投稿者/ にゃるら (26回)-(2018/06/29(Fri) 09:55:24)
No87764 (いまそかり さん) に返信
> Dim fType As Type = Form1.GetType()
>
> Dim f2 As New Form2()
>
> fType.InvokeMember("Form1_Load",
> BindingFlags.NonPublic Or
> BindingFlags.Instance Or
> BindingFlags.InvokeMethod,
> Nothing,
> From1,
> New Object() {Form1, f2}
> )
>
>
> 参考(https://dobon.net/vb/dotnet/programing/invokenonpublicmember.html
> 「隠蔽されている非パブリックメンバを呼び出す」)
>
> これで合ってますかね…?

4つめの引数のFrom1がForm1クラスのインスタンスであればこれでよいと思います。

あと補足でNew Object()の部分は、Form1_Loadの引数になって渡す値ですね。

Form1_Loadの1つ目の引数はsender、これはForm1_Loadメソッドを備えている
Form1のインスタンスを渡してあげる方がよいですね。

2つ目の引数はe、Loadイベントを呼んだ補足情報となるEventArgs型の値です。
特に使うことがないときは、私はEventArgs.Empty(staticなメンバ)を渡してあげます。
何に使うの?っていうと、たとえばですけども、
ClosingイベントだとCancelEventArgsっていう型になっていて、フォームを閉じようとした
ときに、「やっぱり閉じるのやめるわ」ってことがCancelEventArgsのCancelプロパティに
falseを設定することで実現できたりします。
マウスを動かしているときのMouseMoveイベントだとMouseEventArgsg型で、座標の値(x, y)が取れたりします。

> また、以前「基本はPublicではなくPrivateで書いたほうがいい」と授業で習った覚えがあったので、
> Privateで記述していました。

そうですね、その習ったことが間違いとは思いません。
教えられたことを素直に実践するのはとても良いことだと思います。
とはいえ、まずはプログラムは動いてなんぼ。
動く->適切な設定 の順で試される方が良いと思います。(動いた方が楽しいし!)

> でも、まずはにゃるらさんの言う通りPublicでやった方がやりやすいかもですね…。
> 次回からはその方法も試してみます。

時間がもしあるなら、色々試してみてね。
ちなみに僕が回答したリフレクションを使って解決するのは、今回の課題の要件でいけば「適切でない方法」「間違った方法」です。
他の方からの意見は「適切な方法」「正しい方法」です。
いじわるしたわけではないですが、やろとする方法で動くようにすることを提案したまでです。

適切な方法、適切でない方法、正しい方法、間違った方法、どれも「自分で試す」ことが大事だと思います。

出来ればこれからもプログラミングを楽しいと思ってもらえたら幸いです。
でわでわ。
引用返信 編集キー/
■87770 / inTopicNo.11)  Re[5]: 別フォームにデータを渡したい
□投稿者/ いまそかり (5回)-(2018/06/29(Fri) 10:29:53)
No87766 (WebSurfer さん) に返信

おはようございます。
WebSurferさん、回答ありがとうございます。

 
> 上記('Form1_Loadの呼び出し)は何でしょう? 意味がなさそうに見えるのですが。と言うよりこれがエラーの原因???
> 
> frm = New Form2(df) で Form2 を初期化する際に Form1 で生成した DataSet への参照を引数 df 
> 経由で渡して、その後 Form2 の Load イベントのハンドラで、渡された DataSet の情報を元に 
> Form2 に配置されている ComboBox を設定するのではないのですか?
> 
> であれば、そのコードは意味不明&多分不要なのですが・・・




早速指摘されたところを削除してみましたが、エラーは治りませんでした…。
なので、エラーを補足するためにtry catchで囲ってみました。


'ボタンクリックイベント(Form2が開く)
	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
       		
		Try

			Dim frm As Form2
        		frm = New Form2(df) 
        		frm.Show()  '(※1)

		Catch ave As AccessViolationException

		End Try

	End Sub


これで、(※1)に関するエラーは出なくなったのですが、


	'ここでDBから取得した値をコンボボックスに入れる
	Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
		
		'コンボボックスにDB内のテーブルを連結
		ComboBox1.DataSource = df.Tables("テーブル名") '(※2)

            	'コンボボックスに表示したいデータ名
   	        '実際に扱うデータをSelectValueで取得する
      	    	
	End Sub


次は(※2)のところでエラーが発生しました。
エラー内容:NullReferenceException(オブジェクト参照がオブジェクトインスタンスに設定されていません)

どうやらdfの中身がNothingになっていてエラーが出るみたいです。
そのため、Form1のForm1_Load内にあった

Dim ds As DataSet = New DataSet()

を消して、

'Form2のコンストラクタにデータを渡すための引数を入れる変数
	Dim df As DataSet
        ↓
	Dim df As DataSet = New DataSet()

に変えて、変数dsを全部dfにしたら、dfの中身はSystem.Data.DataSetとなり、
df.Tables("テーブル名")の中身は"テーブル名"となりました。

これで実行してみましたが、今度は実行中に応答なしになって、ちゃんと動作してくれませんでした。
何かあと一歩のところまでは来ているような気はするんですが…。
もしかして、dsをdfに変える必要はなかったんですかね…?
ちなみに、変数dsはForm1_Loadでテーブルからレコードを取得する際に

ds.Clear() と da.Fill(ds,"テーブル名") 

といった感じで使用していました。
(変数daは Dim da As New OleDbDataAdapter() です。)


もう少し考えてみますので、よければお力添えをお願いします。

引用返信 編集キー/
■87771 / inTopicNo.12)  Re[4]: 別フォームにデータを渡したい
□投稿者/ PANG2 (213回)-(2018/06/29(Fri) 10:31:38)
やりたいことが、

Fomn1のボタンイベントで、Form2 に DataSet を渡した後に、Form2.Form2_Loadを走らせたい。

であれば、既に解決しているはずです。


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

Dim frm As Form2
frm = New Form2(df)
frm.Show() 'Form2.Form2_Loadが走る
End Sub

No87764 (いまそかり さん) に返信

> また、以前「基本はPublicではなくPrivateで書いたほうがいい」と授業で習った覚えがあったので、
> Privateで記述していました。
> でも、まずはにゃるらさんの言う通りPublicでやった方がやりやすいかもですね…。
> 次回からはその方法も試してみます。

私見では、プログラムは作法を守ることが非常に大切です。(無理やり動かせばよいというものではない)
Form_LoadをPublicにするのは駄目だし、まして外からリフレクションで呼ぶのはトンデモナイ。
引用返信 編集キー/
■87773 / inTopicNo.13)  Re[6]: 別フォームにデータを渡したい
□投稿者/ WebSurfer (1537回)-(2018/06/29(Fri) 11:26:44)
No87770 (いまそかり さん) に返信

C# ですがサンプルを書いておきます。Form5 ⇒ Form1, Form6 ⇒ Form2 に読み替えてください。

デザイナで Form5 には Button を、Form6 には ComboBox をドラッグ&ドロップして、必要なイ
ベントハンドラを生成しただけです。


Form5.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form5 : Form
    {
        public Form5()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            DataTable table = new DataTable();
            table.Columns.Add(new DataColumn("ID", typeof(Int32)));
            table.Columns.Add(new DataColumn("Name", typeof(string)));
            for (int i = 0; i < 5; i++)
            {
                DataRow row = table.NewRow();
                row["ID"] = i;
                row["Name"] = "Product Name_" + i.ToString();
                table.Rows.Add(row);
            }
            DataSet df = new DataSet();
            df.Tables.Add(table);

            Form6 frm = new Form6(df);
            frm.Show();
        }
    }
}


Form6.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form6 : Form
    {
        private DataSet df;

        public Form6()
        {
            InitializeComponent();
        }

        public Form6(DataSet df)
        {
            InitializeComponent();
            this.df = df;
        }

        private void Form6_Load(object sender, EventArgs e)
        {
            comboBox1.DataSource = df.Tables[0];
            comboBox1.DisplayMember = "Name";
            comboBox1.ValueMember = "ID";
        }
    }
}

引用返信 編集キー/
■87776 / inTopicNo.14)  Re[4]: 別フォームにデータを渡したい
□投稿者/ 魔界の仮面弁士 (1725回)-(2018/06/29(Fri) 14:47:52)
a■No87765 (いまそかり さん) に返信
> <修正後ソースコード>
> 'xmlからデータを取得
> Function xmlGet(Byval a As String,Byval b As String)

Function の戻り値のデータ型が示されていません。
戻り値が無いのなら Sub にするべきですし、
戻り値があるのなら、末尾に「As String」などの記述が必要です。


> * 'ボタンクリックイベント(Form2が開く)
> * Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
> *  Dim frm As Form2
> *  frm = New Form2(df)
> *  frm.Show() '(※1)

この段階で、df の中身が Nothing になっていたりはしませんか?


> * 'Form2のオーバーロード(引数あり)
> * Public Sub New()
> *  InitializeComponent()
> * End Sub
> * 'Form2のオーバーロード(引数あり)
> * Public Sub New(df As DataSet)
> *  IntializeComponent()
> *  Me.df = df
> * End Sub

この 2 箇所の IntializeComponent() の行で、[F9]キーを押してブレークポイントを貼り、
この行で一時停止させてみてください。



(※1) からは、後者「Sub New(df As DataSet)」側の IntializeComponent が呼ばれるはずです。
後者が呼ばれた場合は、引数 df が Nothing で無いことを確認してください。
もし、引数に Nothing が渡されるとマズイ場合には、IntializeComponent を呼ぶ前に
 If df Is Nothing Then
  Throw New ArgumentNullException("df")
 End If
などを設けておくとよいでしょう。


一方、前者「Sub New()」側の IntializeComponent が呼ばれることがあるとすれば、
それは想定外の呼び出しとなります。
引数が渡されなければ、Me.df も Nothing のままになってしまうわけで。

もしも前者が呼ばれるようであれば、それがどこから呼び出されているのか
コードを見直してみてみてください。

たとえば、前者を
 Public Sub New()
のままにしただけなら、コンパイルが通る(ただし実行時エラー)のに、それを
 Private Sub New()
にしただけでコンパイルエラーになるようであれば、現在のプロジェクト設定
もしくはコーディングのどこかが間違っているのだと思います。


本来は前者を削除して、後者だけにしたいところなのですが、その場合、
特定の条件を満たしたときに、自動生成される *.designer.vb 内で、
VB のコンパイルエラー BC30109 を生じさせることがあるのが悩ましいところ。

デザイナコードでエラーが生じると、話がややこしくなるため、
No87759 では意図的に、引数なしコンストラクタを残すように案内しています。
(きちんと理解している人なら、前者を削除した状態でも正常に動作するコードを書けるはず)




> fType.InvokeMember("Form1_Load",
>          BindingFlags.NonPublic Or

他の方も書かれていますが、Reflection で解決するのは禁じ手です。
Reflection が必要となるのは、非常に限定された処理であって、
今回のケースで使うようなものではありません。


それに、Form1_Load を自前で呼び出すのも避けるべきです。
イベントハンドラーを、普通のメソッドのように呼び出すことはもちろん可能ですが、
これは本来「呼びだされる物」であって、「呼び出す物」ではありませんので。
引用返信 編集キー/
■87778 / inTopicNo.15)  Re[4]: 別フォームにデータを渡したい
□投稿者/ いまそかり (6回)-(2018/06/29(Fri) 15:20:19)
No87769 (にゃるら さん) に返信

にゃるらさん、回答ありがとうございます。


> あと補足でNew Object()の部分は、Form1_Loadの引数になって渡す値ですね。
> 
> Form1_Loadの1つ目の引数はsender、これはForm1_Loadメソッドを備えている
> Form1のインスタンスを渡してあげる方がよいですね。
> 
> 2つ目の引数はe、Loadイベントを呼んだ補足情報となるEventArgs型の値です。
> 特に使うことがないときは、私はEventArgs.Empty(staticなメンバ)を渡してあげます。
> 何に使うの?っていうと、たとえばですけども、
> ClosingイベントだとCancelEventArgsっていう型になっていて、フォームを閉じようとした
> ときに、「やっぱり閉じるのやめるわ」ってことがCancelEventArgsのCancelプロパティに
> falseを設定することで実現できたりします。
> マウスを動かしているときのMouseMoveイベントだとMouseEventArgsg型で、座標の値(x, y)が取れたりします。
  

解説ありがとうございます!
簡単な例を挙げていただけたので、非常に理解しやすかったです。
少し設定をいじるだけで色々な動作をさせることができるんですね…。



> 動く->適切な設定 の順で試される方が良いと思います。(動いた方が楽しいし!)
 
> ちなみに僕が回答したリフレクションを使って解決するのは、今回の課題の要件でいけば「適切でない方法」「間違った方法」です。
> 他の方からの意見は「適切な方法」「正しい方法」です。
> いじわるしたわけではないですが、やろとする方法で動くようにすることを提案したまでです。
> 
> 適切な方法、適切でない方法、正しい方法、間違った方法、どれも「自分で試す」ことが大事だと思います。 
> 出来ればこれからもプログラミングを楽しいと思ってもらえたら幸いです。


アドバイスもありがとうございます。
以前プログラムが全然書けずに「自分は向いてないんだろうな」と落ち込んでいた時期にも
同じようなことを言って励ましてくれた方がいたので、大変嬉しいです。
私はまだまだ初心者ですが、これからもっと勉強して「正しい方法」と「間違った方法」の
区別をできるように頑張っていきます!

本当に色々とありがとうございました^^






■No87771 (PANG2 さん) に返信

PANG2さん、回答ありがとうございます。

> やりたいことが、
> Fomn1のボタンイベントで、Form2 に DataSet を渡した後に、Form2.Form2_Loadを走らせたい。
> であれば、既に解決しているはずです。
> 
> Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
>       
> 	Dim frm As Form2
>        	frm = New Form2(df) 
>        	frm.Show()  'Form2.Form2_Loadが走る
> End Sub
 

そこまでは上手くできた(と思う)んですが、その後に色々なエラーが出てしまった、という感じでした…。

引用返信 編集キー/
■87783 / inTopicNo.16)  Re[5]: 別フォームにデータを渡したい
□投稿者/ いまそかり (7回)-(2018/06/29(Fri) 16:11:32)
No87773 (WebSurfer さん) に返信

WebSurferさん、回答ありがとうございます。

 
> C# ですがサンプルを書いておきます。Form5 ⇒ Form1, Form6 ⇒ Form2 に読み替えてください。
> 
> デザイナで Form5 には Button を、Form6 には ComboBox をドラッグ&ドロップして、必要なイ
> ベントハンドラを生成しただけです。


サンプルコードありがとうございます!
おかげさまで、無事に実行が成功しました^^


>     public partial class Form5 : Form
>     {
>         public Form5()
>         {
>             InitializeComponent();
>         }


まさかのオーバーロードの書き忘れによるエラーでした…。
(オーバーロードを両方のFormに書く必要があるのだと知らずに初歩的なミスをしていました)

上記のコードをForm1に入れたらちゃんと動くようになりました!

本当にありがとうございました!








■No87776 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士さん、回答ありがとうございます。



>><修正後ソースコード>
>>	'xmlからデータを取得
>>	Function xmlGet(Byval a As String,Byval b As String)
> 
> Function の戻り値のデータ型が示されていません。
> 戻り値が無いのなら Sub にするべきですし、
> 戻り値があるのなら、末尾に「As String」などの記述が必要です。


すみません、今回の質問やエラーに直接関係ないかなと思って戻り値書いていませんでした。
あと、As Stringも書き忘れてますね…申し訳ないです。


 

>>* 'ボタンクリックイベント(Form2が開く)
>>* Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
>>*  Dim frm As Form2
>>*  frm = New Form2(df) 
>>*  frm.Show()  '(※1)
> 
> この段階で、df の中身が Nothing になっていたりはしませんか?
 

はい、その段階でなっていました。多分、dsとdfが混在していたことが原因だったとは思うんですが…。




>>* 'Form2のオーバーロード(引数あり)
>>* Public Sub New()
>>*  InitializeComponent()
>>* End Sub
>>* 'Form2のオーバーロード(引数あり)
>>* Public Sub New(df As DataSet)
>>*  IntializeComponent()
>>*  Me.df = df
>>* End Sub
> 
> この 2 箇所の IntializeComponent() の行で、[F9]キーを押してブレークポイントを貼り、
> この行で一時停止させてみてください。
> 
> (※1) からは、後者「Sub New(df As DataSet)」側の IntializeComponent が呼ばれるはずです。
> 後者が呼ばれた場合は、引数 df が Nothing で無いことを確認してください。
> もし、引数に Nothing が渡されるとマズイ場合には、IntializeComponent を呼ぶ前に
>  If df Is Nothing Then
>   Throw New ArgumentNullException("df")
>  End If
> などを設けておくとよいでしょう。


なるほど、勉強になります。
確かに(※1)からは後者が呼ばれていました。
何でもかんでもtry-catchで囲むんでなく、if文で例外をthrowするといいんですね。
万が一のこともあると思うので、ソースコードに追加します。



 
> 一方、前者「Sub New()」側の IntializeComponent が呼ばれることがあるとすれば、
> それは想定外の呼び出しとなります。
> 引数が渡されなければ、Me.df も Nothing のままになってしまうわけで。
> 
> もしも前者が呼ばれるようであれば、それがどこから呼び出されているのか
> コードを見直してみてみてください。
> 
> たとえば、前者を
>  Public Sub New()
> のままにしただけなら、コンパイルが通る(ただし実行時エラー)のに、それを
>  Private Sub New()
> にしただけでコンパイルエラーになるようであれば、現在のプロジェクト設定
> もしくはコーディングのどこかが間違っているのだと思います。
>  
> 本来は前者を削除して、後者だけにしたいところなのですが、その場合、
> 特定の条件を満たしたときに、自動生成される *.designer.vb 内で、
> VB のコンパイルエラー BC30109 を生じさせることがあるのが悩ましいところ。
> 
> デザイナコードでエラーが生じると、話がややこしくなるため、
> No87759 では意図的に、引数なしコンストラクタを残すように案内しています。
> (きちんと理解している人なら、前者を削除した状態でも正常に動作するコードを書けるはず)


少しのミスでエラーが起きる世界だと改めて分かったので、
もっとプログラミングに関しての知識を深めていけるように頑張ります。

引数なしのコンストラクターは参照0個だし必要あるのかなと疑問でしたが、
これがないだけで発生するエラーがあるんですね…。
今回は特にコンストラクタに対しての指定はないですし理解も不十分なところがあるので、
引数なしコンストラクタを書いておくようにします。
教えていただきありがとうございました。





> Reflection が必要となるのは、非常に限定された処理であって、
 
> それに、Form1_Load を自前で呼び出すのも避けるべきです。
> イベントハンドラーを、普通のメソッドのように呼び出すことはもちろん可能ですが、
> これは本来「呼びだされる物」であって、「呼び出す物」ではありませんので。


なるほど、できるだけ使用しないべきという訳ではなく、特定の条件下で使用するのがベストなんですね。
今回のことでイベントハンドラーは呼び出される物だと分かったので、これからは「メソッドと同じ扱いはしない」
ということを肝に銘じておきます。










回答頂いた皆様、短い間ではありましたが、お付き合いいただき本当にありがとうございました!
まだまだ初心者ですが、皆様のおかげで多くのことを勉強することができました。
この場を借りてお礼申し上げます。
また今後お世話になることもあるかとは思いますが、その時はどうぞよろしくお願いします。

解決済み
引用返信 編集キー/
■87925 / inTopicNo.17)  Re[3]: 別フォームにデータを渡したい
□投稿者/ PANG2 (223回)-(2018/07/13(Fri) 17:38:10)
2018/07/13(Fri) 17:38:55 編集(投稿者)

削除
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -