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

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

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

Re[6]: Newで生成したFormをメインFormから閉じるには


(過去ログ 71 を表示中)

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

■41644 / inTopicNo.1)  Newで生成したFormをメインFormから閉じるには
  
□投稿者/ hs (150回)-(2009/09/26(Sat) 19:57:18)

分類:[VB.NET/VB2005 以降] 

VB2008 VB
いつもお世話になっております。

現在あるデータを登録する際、登録用のFormを作成しております。
この登録用Formは、毎回Newで新たに生成し.Showしており、いくつでも開けるようにしております。

今回開発しているシステムは、ログイン・ログアウトの仕組みを取っていて、
ログイン中に開いた登録用Formをログアウトのタイミングで、1つでも開いていたら全て閉じるという処理で困っています。
色々調べた結果、以下の記述にたどりついたのですが、上手くいきません。

'自フォーム以外の表示しているフォームを全て閉じる
For Each obj As Form In Application.OpenForms
    If obj.Name <> Me.Name Then
        obj.Close()
    End If
Next

上記を実行すると、'コレクションが変更されました。列挙操作は実行されない可能性があります。'とエラー。
内容からすると、Newで生成したFormのためだと思うのですが、いまいち理解できておりません。

メイン(Me)以外のNewで生成したFormを全て閉じる方法はどのようにするべきなのでしょうか?
宜しくお願いします。



引用返信 編集キー/
■41645 / inTopicNo.2)  Re[1]: Newで生成したFormをメインFormから閉じるには
□投稿者/ たくボン (209回)-(2009/09/26(Sat) 20:16:15)
No41644 (hs さん) に返信
> VB2008 VB

> '自フォーム以外の表示しているフォームを全て閉じる
> For Each obj As Form In Application.OpenForms
>     If obj.Name <> Me.Name Then
>         obj.Close()
>     End If
> Next

ここで、For Eachを使ってるからだよ。コレクションの列挙中に、オブジェクトの破棄を行うと次のオブジェクトの列挙ができなくなるから例外が出てるだけ。
For Eachの中で列挙するオブジェクトを破棄する場合は、Forに変更するか、個々の参照を別に持たせてそれを削除するかかな。

For i as integer = 0 to Application.OpenForms.count-1
dim frm as form = Application.OpenForms(i)
 If frm.Name <> Me.Name Then
   frm.Close()
 End If
Next

適当に直したから間違ってたらごめん。
引用返信 編集キー/
■41646 / inTopicNo.3)  Re[2]: Newで生成したFormをメインFormから閉じるには
□投稿者/ 鶏唐揚 (337回)-(2009/09/26(Sat) 20:27:29)
No41645 (たくボン さん) に返信
> ■No41644 (hs さん) に返信
毎回NewでFormを作っているなら通常はそれらを管理するために配列やリストなどにインスタンスを保持しておくべきです。
今回はOpenFormsでも管理できてますが、作り捨てはあまり推奨されません。

あと「自分自身ではない」という判定もNameプロパティでやるのは些か不安ですね。
現在のコード上、必ず異なるNameを振り分けられる保証があったとしても
今後のメンテでどうなるかわからないので。

またOpenFormsは呼び出されるたびに「開いているフォーム」を返します。
よって、たくボンさんの方法ではCloseするたびにOpenFormsの要素数が変わるのに
Forのカウンタ最大値は変わらないのでインデックス範囲外の例外が発生する可能性大です。

OpenFormsを使う方法でやるなら以下のような感じです


'現時点での要素数を維持するためコレクション変数に入れる
Dim forms As FormCollection = Application.OpenForms
Dim i As Integer

For i = 0 To forms.Count - 1
    'Is/IsNot で、インスタンスレベルで同一か調べる
    If forms(i) IsNot Me Then
        forms(i).Close()
    End If
Next

引用返信 編集キー/
■41647 / inTopicNo.4)  Re[3]: Newで生成したFormをメインFormから閉じるには
□投稿者/ hs (151回)-(2009/09/26(Sat) 21:18:24)
No41645 (たくボン さん) に返信
> If frm.Name <> Me.Name Then
>    frm.Close()
> End If

No41646 (鶏唐揚 さん) に返信
> If forms(i) IsNot Me Then
>    forms(i).Close()
> End If

回答ありがとうございます。

いずれの方法も「インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。」
というエラーが出てしまいます。

Newで生成したFormは閉じるたびにDisposeしております。
これが原因なのかと思い、Dispose部分を削除。
しかし相変わらず同じエラーが返ってきます。
ためしにNewで.ShowせずにそのままFormを.Showしてお二人のコードを実行。
これも同じエラーが返ってきます。

ためしにMeにPanelを配置し Me.Panel.Controls.Add(Form)でNewではなく、そのままFormを.Show
逆にDim F As New Formとし Me.Panel.Controls.Add(F)
この場合、両方ともは正常にCloseが行われました。

MeからNewで生成後.Showにしても、そのまま.ShowしたFormにFor文がさしかかると、エラーになります。
どういうことか理解できません。




引用返信 編集キー/
■41648 / inTopicNo.5)  Re[3]: Newで生成したFormをメインFormから閉じるには
□投稿者/ なちゃ (328回)-(2009/09/26(Sat) 21:34:04)
> '現時点での要素数を維持するためコレクション変数に入れる
> Dim forms As FormCollection = Application.OpenForms
> Dim i As Integer
> 
> For i = 0 To forms.Count - 1
>     'Is/IsNot で、インスタンスレベルで同一か調べる
>     If forms(i) IsNot Me Then
>         forms(i).Close()
>     End If
> Next

これも駄目だと思います。

For Each frm As Form In New List(Of Object)(Application.OpenForms)
    If frm IsNot Me Then
        frm.Close()
    End If
Next
とか。

まあちゃんと自分で管理するべきだとは思いますが。

引用返信 編集キー/
■41649 / inTopicNo.6)  Re[4]: Newで生成したFormをメインFormから閉じるには
□投稿者/ なちゃ (329回)-(2009/09/26(Sat) 21:37:07)
みすりましたごめんなさい。

For Each frm As Form In New ArrayList(Application.OpenForms)
    If frm IsNot Me Then
        frm.Close()
    End If
Next

これで。

引用返信 編集キー/
■41650 / inTopicNo.7)  Re[5]: Newで生成したFormをメインFormから閉じるには
□投稿者/ hs (152回)-(2009/09/26(Sat) 21:52:57)
No41649 (なちゃ さん) に返信
> みすりましたごめんなさい。
>
> For Each frm As Form In New ArrayList(Application.OpenForms)
> If frm IsNot Me Then
> frm.Close()
> End If
> Next
>
> これで。


皆さんありがとうございました。
なちゃさんの方法で無事Me以外のFormをすべて閉じる事が出来ました。

ありがとうございました。


それと鳥唐揚の回答で
> 作り捨てはあまり推奨されません。
という事ですが、なにがいけないのでしょうか?
別件ですが、ご教授いただければと

宜しくお願いします。
引用返信 編集キー/
■41651 / inTopicNo.8)  Re[3]: Newで生成したFormをメインFormから閉じるには
□投稿者/ Azulean (462回)-(2009/09/26(Sat) 21:55:23)
No41646 (鶏唐揚 さん) に返信
> For i = 0 To forms.Count - 1

for ループでよくやってしまう罠ですね。
Close した時点で要素が 1 個減って前に詰められてしまう(と思われる)ので、全ての要素を見ることができていないと。
(0 番目を Close したら 元は 1 番目だったものが 0 番目に来る)

別のリストにするという手と、降順( forms.Count - 1 → 0 )にするという手が考えられますね、ぱっと見た限りでは。
引用返信 編集キー/
■41653 / inTopicNo.9)  Re[4]: Newで生成したFormをメインFormから閉じるには
□投稿者/ たくボン (210回)-(2009/09/27(Sun) 00:00:02)
No41651 (Azulean さん) に返信
> ■No41646 (鶏唐揚 さん) に返信
>>For i = 0 To forms.Count - 1
>
> for ループでよくやってしまう罠ですね。
> Close した時点で要素が 1 個減って前に詰められてしまう(と思われる)ので、全ての要素を見ることができていないと。
> (0 番目を Close したら 元は 1 番目だったものが 0 番目に来る)

あぁ、適当にコード書いてたから違ってた。ごめんなさいm(..)m

foreachの場合は、IEnumeratorのMoveNextじゃなかったかな?
だから現在の参照位置のオブジェクトが削除されると、次のオフセット位置がわからないってことだったような気がする。
うろ覚えだから違ってたらごめん。

なちゃさんのようにIListで参照位置を別個に管理するようにNewしとかないとダメでしたね。
引用返信 編集キー/
■41654 / inTopicNo.10)  Re[5]: Newで生成したFormをメインFormから閉じるには
□投稿者/ かずき (46回)-(2009/09/27(Sun) 01:38:18)
>> 作り捨てはあまり推奨されません。
> という事ですが、なにがいけないのでしょうか?
ただ単に、Formのインスタンスの管理をするようなアプリケーションでは
きちんとNewしたFormのインスタンスを自前で管理したほうが楽です。
というくらいのニュアンスだと思います。
(本人じゃないので憶測ですが…)
引用返信 編集キー/
■41671 / inTopicNo.11)  Re[6]: Newで生成したFormをメインFormから閉じるには
□投稿者/ hs (154回)-(2009/09/27(Sun) 22:08:32)
No41654 (かずき さん) に返信
> >> 作り捨てはあまり推奨されません。
>>という事ですが、なにがいけないのでしょうか?
> ただ単に、Formのインスタンスの管理をするようなアプリケーションでは
> きちんとNewしたFormのインスタンスを自前で管理したほうが楽です。
> というくらいのニュアンスだと思います。
> (本人じゃないので憶測ですが…)

みなさんありがとうございました。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -