- PR -

WindowsFormの状態を保持するには?

投稿者投稿内容
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2004-01-08 19:59
Hiroさん、こんばんは。

引用:

作成中のアプリケーションですが、まずはWindowsFormではない自作のクラスから処理を始めるようにしています。
Formの生成やShowDialog、Form間のパラメータの受け渡しは全てこのクラスがつかさどっています。FormからFormを直接呼び出しているわけではありません。



例えばですけど、イメージとしてはこんな感じ↓ですかね?
# VBです。

コード:
Public Shared Sub Main()

F1:
    Dim f1 As Form1 = New Form1

    If Not f1.ShowDialog().Equals(DialogResult.OK) Then
        Exit Sub
    End If

F2:
    Dim f2 As Form2 = New Form2

    If Not f2.ShowDialog().Equals(DialogResult.OK) Then
        GoTo F1
    End If

F3:
    Dim f3 As Form3 = New Form3

    If Not f3.ShowDialog().Equals(DialogResult.OK) Then
        GoTo F2
    End If
End Sub



で、フォームを閉じてしまうと状態が維持されないので、閉じないで非表示にしたいが、そうするとモーダルなダイアログから処理が戻らないし、どうやって画面遷移を制御させようか、という事ですよね?

私ならやはり、各フォームにデリゲートメソッドを持たせて制御用のクラスに通知して処理させますが、どうでしょうか。
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2004-01-08 21:12
引用:

私ならやはり、各フォームにデリゲートメソッドを持たせて制御用のクラスに通知して処理させますが、どうでしょうか。


という事で、ちょっとサンプルを書いてみました。
コード:


// デリゲートメソッドの定義
public delegate void HogeHoge(System.Windows.Forms.DialogResult Result);


// 各フォーム(Form1 〜 Form3)側の記述
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
public HogeHoge hoge;

// フォーム デザイナが生成したコードは省略

// button1.Click イベントハンドラ
private void button1_Click(object sender, System.EventArgs e)
{
this.Hide();
hoge(DialogResult.OK);
}

// button2.Click イベントハンドラ
private void button2_Click(object sender, System.EventArgs e)
{
this.Hide();
hoge(DialogResult.Cancel);
}
}


// メイン(制御)クラス側の記述
public class Class1
{
private Form1 f1 = new Form1();
private Form2 f2 = new Form2();
private Form3 f3 = new Form3();

public Class1()
{
f1.hoge = new HogeHoge(this.f1_Hide);
f2.hoge = new HogeHoge(this.f2_Hide);
f3.hoge = new HogeHoge(this.f3_Hide);
f1.Show();
}

public static void Main()
{
Class1 c1 = new Class1();
System.Windows.Forms.Application.Run();
}

public void f1_Hide(System.Windows.Forms.DialogResult Result)
{
if (Result.Equals(System.Windows.Forms.DialogResult.OK))
{
f2.Show();
}
else
{
System.Windows.Forms.Application.Exit();
}
}

public void f2_Hide(System.Windows.Forms.DialogResult Result)
{
if (Result.Equals(System.Windows.Forms.DialogResult.OK))
{
f3.Show();
}
else
{
f1.Show();
}
}

public void f3_Hide(System.Windows.Forms.DialogResult Result)
{
if (Result.Equals(System.Windows.Forms.DialogResult.OK))
{
System.Windows.Forms.Application.Exit();
}
else
{
f2.Show();
}
}
}



【追記】
ちなみに各フォームの ControlBox プロパティは false にしてあります。


[ メッセージ編集済み 編集者: きくちゃん 編集日時 2004-01-08 21:18 ]
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-01-09 02:14
引用:

Hiroさんの書き込み (2004-01-08 19:13) より:
そして、Form上に配置した「次へ進む」ボタンや、「前へ戻る」ボタンを押した時に自分でCloseメソッドを発行してFormを閉じ、制御クラスへ処理を戻しています。


Hide()もしくはVisible = Falseでフォームを閉じる(実際は非表示にするでけでCloseはしない)ようにすれば、普通に状態が残っているような気がするんですけどそれじゃ駄目?

あれ、もしかしてShowDialog()したら状態は戻ってしまう?いや、そんな事はないような…
すみません、確認できてないですが…
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-01-09 02:40
引用:

Hide()もしくはVisible = Falseでフォームを閉じる(実際は非表示にするでけでCloseはしない)ようにすれば、普通に状態が残っているような気がするんですけどそれじゃ駄目?

あれ、もしかしてShowDialog()したら状態は戻ってしまう?いや、そんな事はないような…
すみません、確認できてないですが…


試してみましたが、ちゃんと状態が残ってました。

あと、ShowDialogで表示したフォームは、Closeで閉じても再度表示できるようです。
ちょっと気持ち悪いし、ドキュメントを読んでもそうはかかれていないように思うんですが、試した限りでは大丈夫のようです。
# まあ、保証は出来ないのでHide()の方が無難かもしれません。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-01-09 02:45
引用:

あと、ShowDialogで表示したフォームは、Closeで閉じても再度表示できるようです。
ちょっと気持ち悪いし、ドキュメントを読んでもそうはかかれていないように思うんですが、試した限りでは大丈夫のようです。


ちょっと気になったんですが、これって気づかずにやってリソースリークしてしまうような気がするんですけど、どうなんでしょう?
まあ、普通はいつかFinalizeで破棄されるでしょうけど…何か気になる…
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-01-09 08:43
引用:

なちゃさんの書き込み (2004-01-09 02:45) より:
引用:

あと、ShowDialogで表示したフォームは、Closeで閉じても再度表示できるようです。


ちょっと気になったんですが、これって気づかずにやってリソースリークしてしまうような気がするんですけど、どうなんでしょう?
まあ、普通はいつかFinalizeで破棄されるでしょうけど…何か気になる…


 聞きかじった程度ですが・・・

 IDisposableインタフェースを実装するクラスは、Disposeメソッドを実装しなければなりません。ただし、「破棄する」操作が「閉じる」操作と同じ意味である場合は、Closeメソッド内で、Disposeメソッドを呼び出すようにして代用します。
 Disposeメソッド内では、GCの処理をすっ飛ばすように、登録を取り消す処理をすることが推奨されています。
 また、GCから登録を解除した後に再使用する場合の処理は2つあって、
1.再使用を許可せず、例外を送出する
2.再度GCに登録し、使用を許可する
だそうです。

 ということは・・・
1.Form.Closeメソッドは、Form.Disposeメソッドの代替か
2.1が真である場合、Disposeメソッド内で登録解除しているか
3.2が真ならば、再登録している


 この内容はASP.NETユーザーズグループのメーリングリストに流れていた内容を、私が理解している範囲でまとめたものです。ツッコミ歓迎。

http://www.divakk.co.jp/aoyagi/csharp_tips_using.html
この辺も参照してください。
架空兎
ベテラン
会議室デビュー日: 2003/08/18
投稿数: 78
お住まい・勤務地: さいたま氏
投稿日時: 2004-01-09 09:59
引用:

Jittaさんの書き込み (2004-01-09 08:43) より:

1.Form.Closeメソッドは、Form.Disposeメソッドの代替か


Windows Form を使っていろいろと調べているときに気付いたのですが、
Form#ShowDialog メソッドで表示したフォームは明示的に
Dispose メソッドを実行しない限り、フォームを閉じても Dispose されないようです。
# Form#Show メソッドで表示したフォームは閉じると Dispose される。

何故、そうなっているのかは良く分かりませんが。。。
#ダイアログを再利用するため??


[ メッセージ編集済み 編集者: 架空兎 編集日時 2004-01-09 10:05 ]
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2004-01-09 11:10
架空兎さん、こんにちは。

引用:

何故、そうなっているのかは良く分かりませんが。。。
#ダイアログを再利用するため??


ShowDialog で表示したフォームが閉じられて呼出元に処理が戻った際に、呼出元がフォームのデータを受け取れるように、ではないでしょうか。

こっち↓は値を受け取れますが、
コード:

Dim F1 As Form1 = New Form1
Dim ret As DialogResult = F1.ShowDialog()

If ret = DialogResult.OK Then
Diagnostics.Debug.WriteLine(F1.TextBox1.Text)
End If



こっち↓は当然、値を受け取れません。
コード:

Dim F1 As Form1 = New Form1
F1.Show()

While F1.Visible ' ← 適当な方法がパッと思いつかなかったので...
Application.DoEvents()
End While

Diagnostics.Debug.WriteLine(F1.TextBox1.Text)



で、やってるうちに気付いたんですが、ShowDialog で表示されたフォーム側で Hide() した場合も、呼出元に戻りますねぇ...。


[ メッセージ編集済み 編集者: きくちゃん 編集日時 2004-01-09 11:15 ]

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