- PR -

画面遷移時に表示順が変わるのを防ぎたい

投稿者投稿内容
さくら
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 76
投稿日時: 2005-11-18 19:23
開発環境
OS:WindowsXP Pro SP1
DB:Oracle10g(ODP.Net10.1.0.3使用)
ツール:VB.NET2003 + .NetFramework1.1 SP1

実行環境
OS:Windows2000 SP4,WindowsXP Pro SP2
ODP.Net10.1.0.3 + .NetFramework1.1 SP1をインストール済

現在、上記の環境でWindowsアプリの開発を行なっております。

画面が3つあり(A,B,Cとします)、
A画面→B画面→C画面というように画面遷移をさせています。

A画面で「B画面へ遷移」ボタンをクリックすると
そのクリックイベントの中で

Dim frmB As formB
frmB = New formB()

AddHandler frmB.Closed, AddressOf Close_frmB

frmB.Show()

Me.Hide()

と記述し、
1.B画面のインスタンス作成
2.B画面が閉じられたときのイベント追加
3.B画面を表示
4.A画面を隠す
という処理を行っています。

次にB画面でも同じように「C画面へ遷移」ボタンをクリックすると
そのクリックイベントの中で
1.C画面のインスタンス作成
2.C画面が閉じられたときのイベント追加
3.C画面を表示
4.B画面を隠す
というソースコードを記述しています。(ソースコードは上記と同じです)

これでC画面を表示し、C画面で「B画面へ戻る」ボタンをクリックしたとき
ボタンのクリックイベントには

Me.Close()

と記述し、C画面を閉じています。
ただこのとき、B画面側でC画面を呼ぶときに作成した
「2.C画面が閉じられたときのイベント追加」イベントが走ります。
B画面で記述しているC画面が閉じられたときのイベントには

Me.Visible = True

と記述しており、C画面が閉じられたらB画面を表示すると
いうようにしています。

これと同じことをA画面でも行なっており、
B画面が閉じられたらA画面を表示すると記述しています。

これで、プログラムを起動させ、
A画面→B画面→C画面→B画面→A画面
というような操作を繰り返し行なっていると
ときどき下記のような現象が発生します。

1.C画面を閉じた後にA画面が前面に来て、
  B画面が背面になる。
2.C画面を閉じた後にA画面が前面に来て、
  前回表示されていたC画面が背面に表示される(残っている)。
  (A1→B1→C1→B1→A1→B2→C2→A1(背面にC1画面))
  
これを防ぎ、必ずA1→B1→C1→B1→A1→B2→C2→B2→A1
というサイクルが行なわれるようにしたいのですが
何が原因でこのような現象が起こっているのか分からず、
防止策が取れずにいます。
(毎回必ず起こるわけではなく、時々忘れた頃に発生します。)

もし何かご存知のことなどありましたら
ぜひ教えてください。よろしくお願い致します。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-11-18 22:06
ウィザードのようなインターフェースを作ろうとしているんだろうけれど、作り方が悪いです。画面上にPanelを配置、Panel上にコントロールを配置し、ウィザードの進行状況に合わせてPanelのVisibleプロパティをTrue/Falseにして画面を切り替えます。
さくら
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 76
投稿日時: 2005-11-18 22:21
お返事ありがとうございます。

ウィザードというイメージではないのですが、
実際には、
A画面がメニュー画面
B画面が商品検索画面
C画面が商品検索結果画面
という作りになっております。
(初回の投稿では書かなかったのですが、
 実際の業務アプリを作っており、
 メニュー画面にはボタンが30個ほどあり、
 画面数は50本ぐらいです。)

メニュー画面で「商品検索」ボタンをクリックすると
商品検索画面を開き(showメソッド使用)、
メニュー画面を隠します(hideメソッド使用)。

商品検索画面で商品分類などを選択し、「検索開始」ボタンをクリックすると
商品検索結果画面を開き(showメソッド使用)、
商品検索画面を隠します(hideメソッド使用)。

商品検索結果画面で、「検索画面に戻る」ボタンをクリックすると
商品検索結果画面を閉じ(closeメソッド使用)
商品検索画面の中の「商品検索結果画面が閉じられたとき」のイベントを
利用して、商品検索画面を表示します(visibleプロパティ使用)。

このような業務アプリの場合でも
パネルで切り替えるのが一般的なのですかね…。
1つ1つ画面(フォーム)を作って、
それを見せたり見せなかったり(開いたり閉じたり)して
切り替えるのが普通だと思っていました…。

もうすでに大半が作り終わってしまっているため
今からパネルに変更するのは修正規模が大きいため
他に何か良い方法や、作り方でまずい点などがありましたら
ぜひ教えてください!!
よろしくお願い致します。
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2005-11-18 23:34
んー、いまいちわからないのですが。

こうゆうことですよね?(長くなるのでイベントハンドラの引数は省略してます)

コード:
Public Class FormA
    Inherits System.Windows.Forms.Form

    Private Sub Button1_Click()
        Dim frmB As FormB
        frmB = New FormB
        AddHandler frmB.Closed, AddressOf Close_frmB
        frmB.Show()
        Me.Hide()
    End Sub

    Private Sub Close_frmB()
        Me.Visible = True
    End Sub
End Class

Public Class FormB
    Inherits System.Windows.Forms.Form

    Private Sub Button1_Click()
        Dim frmC As FormC
        frmC = New FormC
        AddHandler frmC.Closed, AddressOf Close_frmC
        frmC.Show()
        Me.Hide()
    End Sub

    Private Sub Close_frmC()
        Me.Visible = True
    End Sub

    Private Sub Button2_Click()
        Me.Close()
    End Sub
End Class

Public Class FormC
    Inherits System.Windows.Forms.Form

    Private Sub Button1_Click()
        Me.Close()
    End Sub
End Class



自分の環境だと、

引用:

1.C画面を閉じた後にA画面が前面に来て、
  B画面が背面になる。
2.C画面を閉じた後にA画面が前面に来て、
  前回表示されていたC画面が背面に表示される(残っている)。


みたいな現象は発生しないです。
なぜなら、2つの画面が同時に表示されているという状態が無いので。

私、何か勘違いしてるのでしょうか
さくら
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 76
投稿日時: 2005-11-19 02:02
お返事ありがとうございます。

作成していただきましたソースで合っています。
私もそのように作成しています。
ぼのぼの様が投稿の最後に書かれておられますように、
画面が同時に2つ表示されていることは私もありません。

ただ頻繁に画面の順番が入れ替わるわけではなく、
使っていたら時々そういうことが発生するというぐらいで
起こったときの状況(検索に使用した値など)もバラバラで統一性がなく、
余計に原因が分からず、苦戦しております…。

また何かありましたらぜひ教えてください。
よろしくお願い致します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-11-19 06:38
引用:

さくらさんの書き込み (2005-11-18 19:23) より:

A画面で「B画面へ遷移」ボタンをクリックすると
そのクリックイベントの中で

Dim frmB As formB
frmB = New formB()

AddHandler frmB.Closed, AddressOf Close_frmB

frmB.Show()

Me.Hide()

と記述し、
1.B画面のインスタンス作成
2.B画面が閉じられたときのイベント追加
3.B画面を表示
4.A画面を隠す
という処理を行っています。


これでC画面を表示し、C画面で「B画面へ戻る」ボタンをクリックしたとき
ボタンのクリックイベントには

Me.Close()

と記述し、C画面を閉じています。


これ、Close_frmB メソッドを持っているのは、どの画面ですか?B画面じゃないですか?B画面のメソッドで、Me.Close ってやったら、Me はB画面なんじゃないですか?

 Form って、IDisposable … MustDispose なんですけど、Close って、Dispose と同等でしたっけ?ShowModal があるので、なんか、ややこしかったような?
___________________________________________________________________
□ written by Jitta on 2005/11/19
□ Microsoft MVP :Visual Developer ASP/ASP.NET Oct.2005-Sept.2006
_________________
さくら
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 76
投稿日時: 2005-11-21 20:19
お返事ありがとうございます。

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

これでC画面を表示し、C画面で「B画面へ戻る」ボタンをクリックしたとき
ボタンのクリックイベントには

Me.Close()

と記述し、C画面を閉じています。

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

上記の件ですが、 Me.Close としているのは
C画面の中にある「B画面へ戻る」ボタンのClickイベントです。
ですので、閉じられるのはC画面になります。

で、そのC画面が閉じられたときに、
B画面の「C画面が閉じられたとき」メソッドが動作して
B画面をVisible=Trueで表示させています。

CloseとDisposeについてですが、
ShowDialogメソッドで開いたFormについては
明示的にDisposeしなければいけませんが、
Showメソッドで開いたFormについては
Closeすれば自動的にDisposeも行なわれます。

こうやったら必ず現象が発生するというわけではないので
再現させたくても再現できず、非常につらい状況です。

またもし何かありましたらぜひ教えてください。
よろしくお願い致します。
さくら
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 76
投稿日時: 2005-11-24 21:39
同現象が発生し、そのときのエラーが
分かりましたので書き込みをさせていただきます。

A画面→B画面→C画面まで開き、
(このとき、A画面とB画面は隠れている状態)
C画面で「B画面へ戻る」ボタンをクリックすると
以下のエラーメッセージが表示されました。

「”B画面”という名前の、破棄されたオブジェクトに
 アクセスできません。
 オブジェクト名:”B画面”です。」

エラーはSystem.ObjectDisposedExceptionが発生しています。

私が実際に書いているソースコードは
ぼのぼの様が書いてくださっているソースコードと
まったく同じです。

そこで、1つ気になる点があるのですが、
B画面クラス(Public Class FormB)の中で、
B画面からC画面のインスタンスを生成し、
自分自身(B画面)を隠し、
Button1_Clickイベントを終えたとき(End Sub)、
この生成したC画面オブジェクト(frmC)は
自動的に破棄されますよね。
(正確には、破棄してもいいですよという状態で
 メモリ上にはまだ残っていて、
 ガーベジコレクション機能が働いたときに
 実際にメモリ上から開放されると認識しております。)
この状態で、生成されたC画面(今表示されているC画面)の親画面は
隠れているB画面であるというこのつながりが
正しく保持されているのかということが気になっています。

全然的外れなことを言っているかもしれませんが、
何か原因がつかめる糸口になればと思います。
また、何かありましたらぜひ教えてください。
よろしくお願い致します。

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