c#新しいフォームを開いてから、現在のフォームを閉じますか?


89

たとえば、フォーム1を使用しているとすると、次のようになります。

  1. フォーム2を開きます(フォーム1のボタンから)
  2. フォーム1を閉じる
  3. フォーム2に焦点を当てる

18
ひどいユーザビリティ。WinFormsを使用している場合は、コンテナウィンドウを作成し、代わりにパネルを置き換えます。あなたのユーザーはそれのためにあなたを愛するでしょう(そしてそれをしないためにあなたを憎むでしょう)
クラウスヨルゲンセン2011

1
クロースに耳を傾ける!達成しようとしているのは、おそらくa)ウィザードのような一連のステップのwinforms実装、またはb)「データ入力/送信」フォームの後に「結果」フォームを表示する試みです。a)またはb)のどちらであるかに関係なく、実装しようとしているUIの動作は最適ではありません。
Simen S 2011

ClauseとSimenSに感謝します。あなたのコメントは私のような初心者にとって非常に役に立ちます。GUIと使いやすさに関するチュートリアルをもっと読みます。便利なものを教えていただけますか?
tnhan07 2011


あなたの本当の意図が単にログイン(または同様の)フォームを持つことであったかどうか、[ここでの回答](stackoverflow.com/questions/4759334/…)もチェックしてください。
iliasiliadis19年

回答:


194

スティーブの解決策は機能しません。this.Close()を呼び出すと、現在のフォームはform2と一緒に破棄されます。したがって、これを非表示にして、this.Close()を呼び出すためにform2.Closedイベントを設定する必要があります。

private void OnButton1Click(object sender, EventArgs e)
{
    this.Hide();
    var form2 = new Form2();
    form2.Closed += (s, args) => this.Close(); 
    form2.Show();
}

2
ドットネットのWindowsフォームにはClosedイベントはありません。FormClosedイベントか教えていただけますか
Anjali

2
最初のフォームを非表示にしても、それは記憶に残りませんか?そのリソースをどのように解放できますか?
user2635088 2015

5
form2.Closed += (s, args) => this.Close();このステートメントがどのように機能するかを教えてください。正確に(s,args)は何ですか?
Yash Saraiya 2016年

1
(s, args) => this.Close();ラムダ式です。これは、form2.Closedイベントが発生したときに呼び出される「インプレース」関数を作成します。(s, args)ラムダへのパラメーターの単なる名前です。イベントハンドラーの場合、通常はのようなものです(object sender, EventArgs e)Closedイベントデリゲートの署名はそれらのタイプを説明しているため、タイプは指定されていません(必要に応じて誰かが私の言い回しを修正してください)。//全体として、イベントを処理する現在の関数の外部で関数全体(イベントハンドラー)を宣言する必要がないようにするためのトリッキーな方法Form2.Closedです。
kDecker 2016年

1
最初のフォームを非表示にして新しいフォームを開くが、最初のフォームを閉じることはない
UddyanSemwal19年

25

これをやってみてください...

{
    this.Hide();
    Form1 sistema = new Form1();
    sistema.ShowDialog();
    this.Close();
}

これが問題です。メインフォームがあります。しかし、私はログインに小さなフォームを使用します。このフォームは、このメソッドを使用してメインフォームを呼び出します。さて、ここは元気です。問題は、メインフォームに子フォームが表示され、子フォームを閉じるときに...メインフォームも閉じることでした。だから私はNihiqueによって公開された方法を使用しているので。コードは素敵なので、働いている...!
MontDeska

このコードは私のために働いています。私は
VS2015

22

多くの異なる方法が他の回答によってすでに説明されています。ただし、それらの多くは関与しているShowDialog()か、form1開いたままで隠されています。私の意見では、最良かつ最も直感的な方法は、単に閉じform1form2から、外部の場所から作成することです(つまり、これらのフォームのいずれからも作成しません)。form1で作成した場合はMain、以前と同じようにform2簡単に作成できます。シナリオの例を次に示します。Application.Runform1

なんらかの方法で認証するには、ユーザーが資格情報を入力する必要があります。その後、認証が成功した場合は、メインアプリケーションをユーザーに表示したいと思います。これを実現するために、私は2つの形式を使用しています:LogingFormMainForm。にLoginFormは、認証が成功したかどうかを判別するフラグがあります。次に、このフラグを使用して、MainFormインスタンスを作成するかどうかを決定します。これらのフォームはどちらも他のフォームについて知る必要はなく、両方のフォームを適切に開閉できます。このためのコードは次のとおりです。

class LoginForm : Form
{
    public bool UserSuccessfullyAuthenticated { get; private set; }

    void LoginButton_Click(object s, EventArgs e)
    {
        if(AuthenticateUser(/* ... */))
        {
            UserSuccessfullyAuthenticated = true;
            Close();
        }
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        LoginForm loginForm = new LoginForm();
        Application.Run(loginForm);

        if(loginForm.UserSuccessfullyAuthenticated)
        {
            // MainForm is defined elsewhere
            Application.Run(new MainForm());
        }
    }
}

これは、フォームを非表示にするよりも優れたトリックです。アプリケーションを終了するための非表示のフォームがある場合、現在のフォームを閉じるだけでは不十分です。Application.Exit(0)などを使用する必要があります。
Peck_conyon20年

いいのですが、2つのフォームにしか適さないと思います。複数のフォームを切り替えるのはどうですか?
博士MAF

これは、OPが求めたように、フォームを順番に実行することに制限されています。ただし、これが2つのフォームのみに制限される理由はわかりません。外部コードは、必要な数のフォームを順番に自由に生成できます。それらの間の切り替えは、外部コードによっても実行できます。メインフォームの状態(loginForm.UserSuccessfullyAuthenticated以前のように)またはグローバル状態をチェックして、ログインフォームを再実行するか、別のフォームを実行するか、プロセスを終了するかを決定できます。
マヌーザー

11

その行に問題がある:

Application.Run(new Form1()); これはおそらくprogram.csファイルにあります。

この行は、form1がメッセージループを処理することを示しています。つまり、form1はアプリケーションの実行を継続する責任があります。form1が閉じられると、アプリケーションは閉じられます。

これを処理する方法はいくつかありますが、いずれの方法でもform1を閉じることはできません。
(プロジェクトタイプをWindowsフォームアプリケーション以外に変更しない限り)

私があなたの状況に最も簡単だと思うのは、3つのフォームを作成することです。

  • form1-非表示のままでマネージャーとして機能します。必要に応じて、トレイアイコンを処理するように割り当てることができます。

  • form2-ボタンがあり、クリックするとform2が閉じ、form3が開きます。

  • form3-開く必要のある他のフォームの役割を持ちます。

これを実現するためのサンプルコードは次のとおりです
(3番目のフォームからアプリを閉じる例も追加しました)

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1()); //set the only message pump to form1.
    }
}


public partial class Form1 : Form
{
    public static Form1 Form1Instance;

    public Form1()
    {
        //Everyone eveywhere in the app should know me as Form1.Form1Instance
        Form1Instance = this;

        //Make sure I am kept hidden
        WindowState = FormWindowState.Minimized;
        ShowInTaskbar = false;
        Visible = false;

        InitializeComponent();

        //Open a managed form - the one the user sees..
        var form2 = new Form2();
        form2.Show();
    }

}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var form3 = new Form3(); //create an instance of form 3
        Hide();             //hide me (form2)
        form3.Show();       //show form3
        Close();            //close me (form2), since form1 is the message loop - no problem.
    }
}

public partial class Form3 : Form
{
    public Form3()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form1.Form1Instance.Close(); //the user want to exit the app - let's close form1.
    }
}


注:パネルを操作したり、ユーザーコントロールを動的に読み込んだりすることは、業界の生産標準としてより学術的で望ましいことですが、そのためには、この例の方が優れています。

そして、原則が理解されたので、2つの形式で試してみましょう。

  • 最初のフォームは、前の例と同じようにマネージャーの役​​割を果たしますが、最初の画面も表示するため、非表示にするだけで閉じられることはありません。

  • 2番目のフォームは次の画面を表示する役割を果たし、ボタンをクリックするとアプリケーションが閉じます。


    public partial class Form1 : Form
    {
        public static Form1 Form1Instance;

        public Form1()
        {
            //Everyone eveywhere in the app show know me as Form1.Form1Instance
            Form1Instance = this;
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Make sure I am kept hidden
            WindowState = FormWindowState.Minimized;
            ShowInTaskbar = false;
            Visible = false;

            //Open another form 
            var form2 = new Form2
            {
                //since we open it from a minimezed window - it will not be focused unless we put it as TopMost.
                TopMost = true
            };
            form2.Show();
            //now that that it is topmost and shown - we want to set its behavior to be normal window again.
            form2.TopMost = false; 
        }
    }

    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1.Form1Instance.Close();
        }
    }

前の例を変更する場合は、プロジェクトからform3を削除します。

幸運を。


6

具体的ではありませんが、Win Formsアプリで私がやろうとしているようです。ログインフォームから始めて、ログインに成功したら、そのフォームを閉じて、メインフォームにフォーカスを置きます。これが私がそれをする方法です:

  1. frmMainをスタートアップフォームにします。これは私のProgram.csがどのように見えるかです:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new frmMain());
    }
    
  2. 私のfrmLoginで、ログインが成功した場合にのみfalseに初期化され、trueに設定されるパブリックプロパティを作成します。

    public bool IsLoggedIn { get; set; }
    
  3. 私のfrmMainは次のようになります:

    private void frmMain_Load(object sender, EventArgs e)
    {
        frmLogin frm = new frmLogin();
        frm.IsLoggedIn = false;
        frm.ShowDialog();
    
        if (!frm.IsLoggedIn)
        {
            this.Close();
            Application.Exit();
            return;
        }
    

ログインに失敗しましたか?アプリケーションを終了します。それ以外の場合は、frmMainを続行します。スタートアップフォームなので、閉じるとアプリケーションが終了します。


3

このコードスニペットをform1で使用します。

public static void ThreadProc()
{
Application.Run(new Form());
}

private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc));
t.Start();
this.Close();
}

ここからもらっ


リンクのみの回答は推奨されないことに注意してください。SOの回答は、解決策の検索のエンドポイントである必要があります(これに対して、時間の経過とともに古くなる傾向がある参照のさらに別のストップオーバー)。リンクを参照として保持しながら、ここにスタンドアロンの概要を追加することを検討してください。
kleopatra 2013

2

frm_form1とfrm_form2の2つのフォームがある場合。次のコードは、frm_form2を開いてfrm_form1を閉じるために使用されます。(Windowsフォームアプリケーションの場合)

        this.Hide();//Hide the 'current' form, i.e frm_form1 
        //show another form ( frm_form2 )   
        frm_form2 frm = new frm_form2();
        frm.ShowDialog();
        //Close the form.(frm_form1)
        this.Close();

1

私は通常、フォームを切り替えるためにこれを行います。

まず、プログラムファイルにApplicationContextを保持し、ヘルパーSwitchMainFormメソッドを追加します。

        static class Program
{
    public static ApplicationContext AppContext { get;  set; }


    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        //Save app context
        Program.AppContext = new ApplicationContext(new LoginForm());
        Application.Run(AppContext);
    }

    //helper method to switch forms
      public static void SwitchMainForm(Form newForm)
    {
        var oldMainForm = AppContext.MainForm;
        AppContext.MainForm = newForm;
        oldMainForm?.Close();
        newForm.Show();
    }


}

次に、コードの任意の場所でSwitchMainFormメソッドを呼び出して、新しいフォームに簡単に切り替えます。

// switch to some other form
var otherForm = new MyForm();
Program.SwitchMainForm(otherForm);

0
private void buttonNextForm(object sender, EventArgs e)
{
    NextForm nf = new NextForm();//Object of the form that you want to open
    this.hide();//Hide cirrent form.
    nf.ShowModel();//Display the next form window
    this.Close();//While closing the NextForm, control will come again and will close this form as well
}

それは動作しません。次のフォームを表示する前に非表示にする意味はありません。同時に実行され、プログラムは終了します。
Ahmet Karabulut 2018年

0
//if Form1 is old form and Form2 is the current form which we want to open, then
{
Form2 f2 = new Form1();

this.Hide();// To hide old form i.e Form1
f2.Show();
}

0

このコードはあなたを助けるかもしれません:

Master frm = new Master();

this.Hide();

frm.ShowDialog();

this.Close();

これはアプリケーションが存在します
Baqer Naqvi 2017

0
                     this.Visible = false;
                        //or                         // will make LOgin Form invisivble
                        //this.Enabled = false;
                         //  or
                       // this.Hide(); 



                        Form1 form1 = new Form1();
                        form1.ShowDialog();

                        this.Dispose();

1
この答えはこの議論に追加されますか?他の9つの回答にある説明情報を追加せずに言い換えています。
エドワード

0

これははるかに簡単だと思います:)

    private void btnLogin_Click(object sender, EventArgs e)
    {
        //this.Hide();
        //var mm = new MainMenu();
        //mm.FormClosed += (s, args) => this.Close();
        //mm.Show();

        this.Hide();
        MainMenu mm = new MainMenu();
        mm.Show();

    }

この解決策は、この質問に関連する回答ではありません。ソリューションは現在のフォームを閉じません。これは、現在のフォームがまだ処理中であることを意味します。
AhmetKarabulut18年

-1

2つのフォームがあり、最初のフォーム名がForm1で、2番目のフォーム名がForm2であるとします。Form1からForm2にジャンプして、ここにコードを入力する必要があります。次のようなコードを記述します。

Form1にはButton1という名前のボタンが1つあり、そのクリックオプションに以下のコードを記述します。

protected void Button1_Click(Object sender,EventArgs e)
{
    Form frm=new Form2();// I have created object of Form2
    frm.Show();
    this.Visible=false;
    this.Hide();
    this.Close();
    this.Dispose();
}

このコードがお役に立てば幸いです


これらの4つの方法:this.Visible=false; this.Hide(); this.Close(); this.Dispose();冗長です。必要なのはClose()。フォームを閉じるとフォームが破棄され、フォームの可視性を設定することは非表示にすることと同じです。フォームを非表示にすることは、次のペイントイベントの前に存在しない場合は無意味です。
Servy 2012年

-3

私はそれを次のようにして解決します:

private void button1_Click(object sender, EventArgs e)
{
    Form2 m = new Form2();
    m.Show();
    Form1 f = new Form1();
    this.Visible = false;
    this.Hide();
}

3
this.Visible = falseそしてthis.Hide?なぜ同じことを2回行うのですか?
ネオリスク2012年

8
また、なぜ新しいものを作成しForm1、それで何もしないのですか?
Servy 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.