テキスト ボックス、ドロップダウン、チェック ボックス、グループ ボックス内の上記すべて、およびいくつかのラベルを含むタブ ページがあります。ユーザーがボタンをクリックしたときに、すべてのコントロールをクリアしたいと思います。どのように実装すればよいですか?標準ライブラリメソッドがあると思って、たくさん検索しました。私が見つけたのは、for-eachループを使用したいくつかのメソッドでした(グループボックス内では機能しません)。この問題の進め方を教えてください。基本的に、Tabpage.load(); のようなメソッドが必要です。タブを初期状態に戻します。可能であれば、特定のテキスト ボックスを保持したいと考えています。
4 に答える
多くの Winforms プログラマーは、この種のコードを誤解しています。これまでに得た答えも例外ではありません。Controls.Clear() および Controls.Remove() メソッドは非常に危険です。メソッドは、意図したとおりに親からコントロールを削除しますが、コントロールを破棄しません。それらは、「ParkingWindow」という名前の内部非表示ウィンドウで再ホストされます。ネイティブ ウィンドウを存続させ、別の親ウィンドウに移動できるようにします。
これは非常に優れた機能ですが、残念ながら制御不能なウィンドウ ハンドル リークの主な原因となっています。断然、実際の意図はそれらを破棄することであり、再ホストすることではないからです。コントロールを完全に削除するには、その Dispose() メソッドを使用する必要があります。Controls コレクションからも自動的に削除されます。
これは 2 番目のトラップです。foreach を使用して Controls コレクションを反復処理することはできません。これは、コレクションが foreach ループによって変更されることの副作用である、偶数番号のコントロールのみを破棄します。代わりに、次のように逆方向に反復する必要があります。
public static void UnloadTabpage(TabPage page) {
for (int ix = page.Controls.Count - 1; ix >= 0; --ix) {
page.Controls[ix].Dispose();
}
}
また、ジャスティンのように再帰しないでください。コントロールを破棄すると、そのコントロールの子コントロールも自動的に破棄されます。グループ ボックスに問題がある可能性がありますが、あまり明確ではありません。
キックのために、これは本当に要点を家に追いやる別の実装です:
public static void UnloadTabpage(TabPage page) {
while (page.Controls.Count > 0) page.Controls[0].Dispose();
}
しかし、それでは、やりたいと言ったように、コントロールを選択的に削除することは簡単ではありません。
メソッドを使用しControlCollection.Clear()
ます。MSDN
myTabControl.Controls.Clear()
特定のコントロールを保持したい場合は、次のいずれかを実行できます。
- 列挙と条件チェックを使用して、必要なコントロールのみを削除します。
- すべてのコントロールをクリアしてから、保持したいものだけを再読み込みします。
保持するコントロールの数と削除するコントロールの数によって異なります。
まず、各種類のコントロールの「クリア」を意味するものを決定する必要があります。つまり、TextBox ではテキストを strimg.Empty に設定し、CheckBox では Checked を false に設定し、Label では何もしないことを意味します。GroupBox の場合、クリアはそのコントロールを再帰的にクリアすることを意味します。何をするかを決定したら、デリゲート タイプを定義し、コントロールのタイプがキーであるこれらのデリゲートのディクショナリを作成できます。これで、適切なデリゲートを適用してコントロール コレクションをループできます。コードは説明よりも簡単です。
public delegate void ClearControl(Control aCtrl);
private static Dictionary<Type, ClearControl> _clearDelegates;
public static Dictionary<Type, ClearControl> ClearDelegates
{
get
{
if (_clearDelegates== null)
InitializeClearDelegates();
return _clearDelegates;
}
}
private static void InitializeClearDelegates()
{
_clearDelegates= new Dictionary<Type, ClearControl>();
_clearDelegates[typeof(TextBox)] = new ClearControl(delegate(Control aCtrl)
{
((TextBox)aCtrl).Text = string.Empty;
});
_clearDelegates[typeof(CheckBox)] = new ClearControl(delegate(Control aCtrl)
{
((CheckBox)aCtrl).Checked = false;
});
_clearDelegates[typeof(GroupBox)] = new ClearControl(delegate(Control aCtrl)
{
foreach (Control innerCtrl in ((GroupBox)aCtrl).Controls)
Clear(innerCtrl);
});
_clearDelegates[typeof(TabPage)] = new ClearControl(delegate(Control aCtrl)
{
foreach (Control innerCtrl in ((TabPage)aCtrl).Controls)
Clear(innerCtrl);
});
// ... other controls
}
public static object Clear(Control aCtrl)
{
ClearControl aDel;
if (ClearDelegates.TryGetValue(aCtrl.GetType(), out aDel))
aDel(aCtrl);
}
これは私にとってはうまくいきます.GroupBoxが含まれています.
void ClearControls(Control parent)
{
while (parent.Controls != null && parent.Controls.Count > 0)
{
ClearControls(parent.Controls[0]);
parent.Controls.Remove(parent.Controls[0]);
}
}