如何在不创建新的表单实例的情况下在表单之间切换?

Posted

技术标签:

【中文标题】如何在不创建新的表单实例的情况下在表单之间切换?【英文标题】:How to switch between forms without creating new instance of forms? 【发布时间】:2014-04-17 16:07:42 【问题描述】:

在我的应用程序中,我有四个表单 form1 form2 form3 form4 。每个表单都有两个按钮,即在表单之间切换的下一个和上一个按钮。我的问题是下面是我的代码

在表格 1 中:

    public Form1()
   
       InitializeComponents();
   

    private void Next_Click(object sender, EventArgs e)
    
      this.Hide()
       Form2  form2 = new Form2();
       form2.Show();
          

在 Form2 中:

    public Form2()
   
       InitializeComponents();
   
    private void Previous_Click(object sender, EventArgs e)
    
       this.Hide();
       Form1 form1 = new Form1();
       form1.Show();
    

    private void Next_Click(object sender, EventArgs e)
    
         this.Hide();
       Form3 form3 = new Form3();
       form3.Show();
          

在 Form3 中:

    public Form3()
   
       InitializeComponents();
   
    private void Previous_Click(object sender, EventArgs e)
    
        this.Hide();
       Form2 form2 = new Form2();
       form2.Show();
    

    private void Next_Click(object sender, EventArgs e)
    
         this.Hide();
       Form4 form4 = new Form4();
       form4.Show();
          

在 Form4 中:

    public Form4()
   
       InitializeComponents();
   
    private void Previous_Click(object sender, EventArgs e)
    
         this.Hide();
       Form3 form3 = new Form3();
       form3.Show();
    

在主要:

static void Main()
    
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.Run(new Form1());


    

在上面的代码中,我每次都在创建新的表单实例..,我怎样才能避免这种情况以及如何在不创建新的表单实例的情况下在表单之间切换......请帮助我

【问题讨论】:

在全局类中保留所有表单的公共静态变量。在form1初始化函数中初始化form2、form3、form4。然后根据需要激活或隐藏。 任何对你有帮助的答案请标记为答案 感谢您的建议.. @ray 你能把你的答案作为代码发布吗?它可能只是为我做这项工作,我会更好地理解你在说什么...... :) 【参考方案1】:

由于您是按顺序访问表单,因此只需确保使用 Show 方法将所有者分配给创建的表单,并在创建后将其分配给类级别变量。像这样的东西应该适合你。

Form1

public partial class Form1 : Form

    Form2 frm2;
    public Form1()
    
        InitializeComponent();
    

    private void button1_Click(object sender, EventArgs e)
    
        if (frm2 == null)
        
            frm2 = new Form2();   //Create form if not created
            frm2.FormClosed += frm2_FormClosed;  //Add eventhandler to cleanup after form closes
         

        frm2.Show(this);  //Show Form assigning this form as the forms owner
        Hide();
    

    void frm2_FormClosed(object sender, FormClosedEventArgs e)
    
        frm2 = null;  //If form is closed make sure reference is set to null
        Show();
    

Form2

public partial class Form2 : Form

    Form3 frm3;
    public Form2()
    
        InitializeComponent();
    

    private void button1_Click(object sender, EventArgs e)
    
        Owner.Show();  //Show the previous form
        Hide();

    

    private void button2_Click(object sender, EventArgs e)
    
        if (frm3 == null)
        
            frm3 = new Form3();
            frm3.FormClosed += frm3_FormClosed;
        

        frm3.Show(this);
        Hide();
    

    void frm3_FormClosed(object sender, FormClosedEventArgs e)
    
        frm3 = null;
        Show();
    

Form3

public partial class Form3 : Form

    public Form3()
    
        InitializeComponent();
    

    private void button1_Click(object sender, EventArgs e)
    
        Owner.Show();
        Hide();
    

【讨论】:

谢谢您,先生,您的代码建议真的很有帮助,非常感谢您.....【参考方案2】:

可能是一个简单的解决方案。您可以创建一个包含您需要的所有形式的静态对象的类。因此,您将能够从您选择的任何表单中访问所有这些表单,而且它们被初始化一次。

public class formList

      private static Form1 _form1 = new Form1();
      public static Form1 form1  get return _form1;
      .................
      ............

【讨论】:

【参考方案3】:

试试这个:

Form1 myForm =(Form1) Application.OpenForms["Form1"];
myForm.Show();

【讨论】:

但这要求表单已经打开。并且按名称引用表单我称之为丑陋。 尽管有@PMF 的评论,但这正是我所需要的!我能找到的所有其他案例都只提到了实例化表单的一个新实例......在我的案例中,我想操作一个已经打开的当前表单。【参考方案4】:

您可以检查感兴趣的表单是否存在,如果不存在则创建

public static T OpenOrCreateForm<T>() 
  where T: Form, new() 

  T result;

  // Test if form exists
  foreach(Form form in Application.OpenForms) 
    result = form as T;

    if (!Object.ReferenceEquals(null, result)) 
      // Form found; and this is the right place 
      //  to restore form size,
      //  bring form to front etc.
      if (result.WindowState == FormWindowState.Minimized)
        result.WindowState = FormWindowState.Normal;

      result.BringToFront();

      return result;
    
  

  // Form doesn't exist, let's create it
  result = new T();
  // Probably, you want to show the created form
  result.Show();

  resturn result;


...
private void Previous_Click(object sender, EventArgs e)

   Hide();
   OpenOrCreateForm<Form1>();
 

private void Next_Click(object sender, EventArgs e)

   Hide();
   OpenOrCreateForm<Form3>();
   

【讨论】:

【参考方案5】:
  public bool IsFormAlreadyOpen(Type FormType)
        
            foreach (Form OpenForm in Application.OpenForms)
            
                if (OpenForm.GetType() == FormType)
                    return true;
            
            return false;
        

这个函数可以用来判断表单是否已经打开

调用IsFormAlreadyOpen(Form4)如果它返回true,这意味着Form4已经打开

在你的情况下

every forms constructor() 中创建下一个和上一个表单对象

并在按钮中单击调用 IsFormAlreadyOpen() 以查看表单是否已打开,如果已打开,只需将该表单放在前面 否则使用 obj.show() 方法显示表单 并隐藏或关闭父窗体

【讨论】:

【参考方案6】:

看起来您正在尝试实现类似向导的功能。我建议使用单一表格。然后,向其中添加自定义选项卡控件。将按钮添加到移动上一个和下一个的表单。

要自定义选项卡控件,您需要这样做:

public class CustomWizard : TabControl

    /// <summary>
    /// This method traps windows message and hides other tabs in the tab control.
    /// Message trapped: TCM_ADJUSTRECT
    /// </summary>
    /// <param name="m">Reference to Windows message</param>
    protected override void WndProc(ref Message m)
    
        // Second condition is to keep tab pages visible in design mode
        if (m.Msg == 0x1328 && !DesignMode)
        
            m.Result = (IntPtr)1;
        
        else
        
            base.WndProc(ref m);
        
    

    /// <summary>
    /// This method traps the press to stop users from selecting tab page via keyboard
    /// </summary>
    /// <param name="ke">Event details</param>
    protected override void OnKeyDown(KeyEventArgs ke)
    
        if (ke.Control && ke.KeyCode == Keys.Tab)
            return;

        base.OnKeyDown(ke);
    

    private void InitializeComponent()
    
        this.SuspendLayout();
        this.ResumeLayout(false);

    

此选项卡控件一次仅显示一个选项卡。虽然,在设计时你可以看到它们。将此和按钮添加到您的表单中。单击按钮时,只需设置此选项卡控件的SelectedIndex 属性即可。

【讨论】:

【参考方案7】:

我有同样的问题。我需要一个有很多表单的应用程序,我需要在不丢失数据的情况下向前 n 向后切换表单。我想出了以下解决方案,它对我有用。

在主(Program.cs)文件中,编写如下两个类:

static class Variables

    public static DataSet Configurations = new DataSet();

    public static float ExchangeRate = 0;

    public static Dictionary<string, int> ItemsCategories = new Dictionary<string, int>();

    public static Dictionary<string, float> WeightUnits = new Dictionary<string, float>();


static class Forms

    public static Form2 F_Form2 = new Form2();

    public static Form3 F_Form3 = new Form3();


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());
    

第一个类用于可以跨表单使用的全局变量。您可以通过以下方式访问任何变量:

Variables.ExchangeRate = 7.2; //(for ex).

第二个类是您定义所有表单的新实例的地方。您可以通过以下方式在所有表单的任何位置隐藏 n 显示它们:

Forms.F_Form3.Show();

Forms.F_Form2.Hide();

这对我来说运行顺利且完美。试试看。

【讨论】:

【参考方案8】:

只需删除第一个表单中的this.hide() 和第二个表单中的[formNameHere].show();

像这样:

表格一:

public Form1()

    InitializeComponents();


private void Next_Click(object sender, EventArgs e)

    this.Hide()
    Form2  form2 = new Form2();
    form2.Show();
 

表格二:

public Form2()

    InitializeComponents();


private void Previous_Click(object sender, EventArgs e)

    Form1 form1 = new Form1();
    this.Hide();


private void Next_Click(object sender, EventArgs e)

    Form3 form3 = new Form3();
    this.Hide();
  

etc.. 不擅长解释,而且真的用 C#。但这应该可行。

【讨论】:

【参考方案9】:
    //In Form1
private static Form1 i_Instance = null;
public static Form1 Instance
   
      get
      
        if (Form1.i_Instance == null) Form1.i_Instance = new Form1();
        return Form1.i_Instance;
      
   
// And instantiation in other forms shall look like following
Form1 F1 = Form1.Instance;
F1.Show();

【讨论】:

如果我选择说 Form0 作为主表单 (Application.Run(new Form0()) 并从此表单打开其他表单,则此方法有效。请注意,如果进行 Form0 实例化尝试,该方法将不起作用来自从 Form0 调用的其他表单的任何实例(每个实例只有一个)。在这种情况下,程序会编译但不会运行

以上是关于如何在不创建新的表单实例的情况下在表单之间切换?的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery-AJAX 向 PHP 提交表单并在不刷新的情况下在 div 中显示新内容的问题

在不使用故事板中的导航控制器的情况下在 UIViewController 之间切换的最佳方法是啥?

如何在不重复的情况下在进程之间共享大量数据? (IPC)

如何在不通过视图在所有页面中发送表单的情况下从 django 布局(如“base.html”)获取表单数据?

Vim ctags:我们可以在不关闭 taglist 窗口的情况下在 taglist 窗口和源代码窗口之间切换焦点吗?

如何在不使用服务的情况下将子组件之间的反应式表单数据传递给父组件