Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关闭所有子窗体时退出应用程序_C#_Forms_Winforms_Parent Child_Exit - Fatal编程技术网

C# 关闭所有子窗体时退出应用程序

C# 关闭所有子窗体时退出应用程序,c#,forms,winforms,parent-child,exit,C#,Forms,Winforms,Parent Child,Exit,在我的winform应用程序中,有一个窗体在for循环期间创建其他窗体。此父窗体保持隐藏状态,仅用于处理 我将处理代码从程序类中移出,因为Application.Run似乎没有将nice放入循环中,因为会打开多个实例 完成子窗体后,它们将关闭。我想知道的是,即使父窗体仍然打开,当这些窗体关闭时,我是否可以让应用程序退出。我已尝试在父窗体上公开一个列表,以存储哪些窗体已关闭,但子窗体无法访问该列表,因为父窗体没有实例名称-它由应用程序调用。Run(new FormProcessor(args))

在我的winform应用程序中,有一个窗体在for循环期间创建其他窗体。此父窗体保持隐藏状态,仅用于处理

我将处理代码从程序类中移出,因为
Application.Run
似乎没有将nice放入循环中,因为会打开多个实例

完成子窗体后,它们将关闭。我想知道的是,即使父窗体仍然打开,当这些窗体关闭时,我是否可以让应用程序退出。我已尝试在父窗体上公开一个
列表
,以存储哪些窗体已关闭,但子窗体无法访问该列表,因为父窗体没有实例名称-它由
应用程序调用。Run(new FormProcessor(args))


更一般地说,我想我是在问是否有一种方法可以从子窗体访问父窗体的属性

在每个子窗体的构造函数中插入对父窗体的引用,从而允许访问它


或者在创建每个子窗体时,在父窗体中添加对列表的引用,然后运行后台任务以等待所有子窗体关闭。您可以通过订阅每个子窗体上的form closed事件并等待这些事件触发来完成此操作。下面是我试图在注释中显示的一个简单示例

您可以创建一个额外的类来处理FormClosed事件的注册,例如:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Forms;

namespace wfAutoClose {
  public class FormSubscriber : INotifyPropertyChanged, IDisposable {
    public event PropertyChangedEventHandler PropertyChanged;

    private readonly IList<Form> _forms = new ObservableCollection<Form>();
    public IList<Form> Forms {
      get {
        return _forms;
      }
    }

    public int FormCount {
      get {
        return _forms.Count;
      }
    }

    private void RaisePropertyChanged(string propertyName) {
      var localEvent = PropertyChanged;
      if (localEvent != null) {
        localEvent.Invoke( this, new PropertyChangedEventArgs( propertyName: propertyName ) );
      }
    }

    private void OnChildFormClosed(object sender, FormClosedEventArgs e) {
      Forms.Remove( sender as Form );
    }

    private void SubscribeToFormClosedEvent(Form childForm) {
      childForm.FormClosed += OnChildFormClosed;
    }

    private void UnsubscribeFromFormClosedEvent(Form childForm) {
      childForm.FormClosed -= OnChildFormClosed;
    }

    private void OnChildFormCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
      if (e.OldItems != null) {
        foreach (var item in e.OldItems) {
          UnsubscribeFromFormClosedEvent( item as Form );
        }
      }
      if (e.NewItems != null) {
        foreach (var item in e.NewItems) {
          SubscribeToFormClosedEvent( item as Form );
        }
      }
      RaisePropertyChanged( "FormCount" );
    }

    public void Dispose() {
      ( Forms as INotifyCollectionChanged ).CollectionChanged -= OnChildFormCollectionChanged;
    }

    public FormSubscriber() {
      ( Forms as INotifyCollectionChanged ).CollectionChanged += OnChildFormCollectionChanged;
    }
  }
}

当然,在我的示例中,它们只是基本窗口,我不关心任何线程或其他GUI细节,但它应该向您展示如何使用事件注册和
ObservableCollection
(请参阅FormSubscriber)的基本功能最简单的方法是在其他一些全局类中保存有关打开/关闭表单的信息,如:

public static class Helper
{
   public static List<int> ChildFormsOpened { get; private set; }

   static Helper()
   {
       ChildFormsOpened = new List<int>();   
   }
}
因此,在代码中的某个时刻,您可以从集合中删除正在关闭的表单,并检查是否所有其他表单也已关闭。如果是,则可以通过调用
application.Exit()
方法关闭应用程序:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
       Helper.ChildFormsOpened.Remove(this.GetHashCode());
       if(Helper.ChildFormsOpened.Count < 1) Application.Exit();
    }    
private void Form1\u FormClosing(对象发送方,FormClosingEventArgs e)
{
Helper.ChildFormsOpened.Remove(this.GetHashCode());
if(Helper.ChildFormsOpened.Count<1)Application.Exit();
}    

使用ApplicationContext并订阅所有子窗体的FormClosed()事件。检查Application.OpenForms集合并在适当时退出()

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyContext());
    }

}

public class MyContext : ApplicationContext
{

    public MyContext()
    {
        // Open your Forms...
        for(int i = 1; i <= 5; i++)
        {
            Form frm = new Form();
            frm.Text = "Form #" + i.ToString();
            frm.FormClosed += Frm_FormClosed;
            frm.Show(); 
        }
    }

    private void Frm_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (Application.OpenForms.Count == 0)
        {
            Application.Exit();
        }
    }

}
静态类程序
{
/// 
///应用程序的主要入口点。
/// 
[状态线程]
静态void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
运行(新的MyContext());
}
}
公共类MyContext:ApplicationContext
{
公共MyContext()
{
//打开你的表格。。。

对于(int i=1;i感谢所有帮助过我的人。我找到了一个适合我的答案。我在关闭的表单后面添加了一个事件处理程序。
origList
变量存储
formList
的原始数据,否则
foreach
将进入列表的下一个条目,该条目可能已被删除

for ( int i =0; i < formList.Count; i++)
        {
                string formName = formList[i];

                    Form1 frm = (new Form1(formName...);
                    frm.Show();
                    string contextName= formName;
                    frm.FormClosed += new FormClosedEventHandler((sender, e) => FrmClosed_Event(sender, e, contextName));                                     
        }

       public void FrmClosed_Event(object sender, FormClosedEventArgs e, string name)
        {
            foreach(string thisForm in origList)
            {
                if (thisForm == name)
                { formList.Remove(thisForm); }
            }
            if (formList.Count == 0)
            { Application.Exit(); }
        }
for(int i=0;iFrmClosed_事件(发送方,e,contextName));
}
public void FrmClosed_事件(对象发送方,FormClosedEventArgs e,字符串名称)
{
foreach(在origList中字符串此表单)
{
if(thisForm==名称)
{formList.Remove(thisForm);}
}
如果(formList.Count==0)
{Application.Exit();}
}

您可以使用共享的viewmodel,该viewmodel从父窗体中初始化,并作为构造函数参数或属性提供给子窗体。另一方面,所有子窗体都应该有一个
FormClosed
事件,您可以将自己绑定到该事件,当窗体关闭时,您可以删除对fo的引用rm从您的列表中删除,一旦您有一个空列表,您就调用
应用程序。退出
这一切似乎都是一种不必要的黑客行为,用于替换需要检查ChildFormOpened列表是否为0的组件?关闭列表的人,或者在您的示例中不知道某些内容已关闭的家长?嗯,这取决于项目需要将从哪个类进行此检查。但我想在子
FormClosing
事件处理程序中进行检查是最简单的选择。当每个子窗体即将关闭时,它将进行此检查,如果需要(所有窗体都已关闭)-关闭ApplicationTanks@icepickle,我采用了类似的方法。
Form1 frm=new Form1(formname…;frm.Show();frm.FormClosed+=new formClosedEventHandler((sender,e)=>FormClosed\u事件(sender,e,formname));
static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyContext());
    }

}

public class MyContext : ApplicationContext
{

    public MyContext()
    {
        // Open your Forms...
        for(int i = 1; i <= 5; i++)
        {
            Form frm = new Form();
            frm.Text = "Form #" + i.ToString();
            frm.FormClosed += Frm_FormClosed;
            frm.Show(); 
        }
    }

    private void Frm_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (Application.OpenForms.Count == 0)
        {
            Application.Exit();
        }
    }

}
for ( int i =0; i < formList.Count; i++)
        {
                string formName = formList[i];

                    Form1 frm = (new Form1(formName...);
                    frm.Show();
                    string contextName= formName;
                    frm.FormClosed += new FormClosedEventHandler((sender, e) => FrmClosed_Event(sender, e, contextName));                                     
        }

       public void FrmClosed_Event(object sender, FormClosedEventArgs e, string name)
        {
            foreach(string thisForm in origList)
            {
                if (thisForm == name)
                { formList.Remove(thisForm); }
            }
            if (formList.Count == 0)
            { Application.Exit(); }
        }