none
wpf,怎么判断某个类型的子窗体是否全部都关闭了? RRS feed

  • 问题

  • 问这个问题的原因是有这样的一个可能,就是用户可能会在一段时间内重复做出包含"向数据库添加数据的"操作。这个行为就是类似{用户复制大文件到另一个文件夹中,开启复制窗口,复制过程还没完,用户又开启新的复制任务,开启新的复制窗口等},类似这样的

    例如不停点击某个按钮,该按钮的事件就是“向某个数据库添加数据,点击后会以调用show方法弹出一个等待窗口,并把添加的数据传送到这个子窗口中,在这个窗口对象中向数据库添加数据,完成后调用close关闭等待窗口”的这个过程,

    有时候数据量很大,可能会长时间等待,这个时候用户可以在点击按钮,添加另一段数据到数据库,然后又会开启另一个等待窗口,并……等。假设这样的窗口开启了很多,我担心用户可能会手贱,点击了主窗口的关闭按钮会发生不可预知的事情,那么就得判断这个类型的子窗口是否全部都处于关闭状态了,如果都关闭了,才能关闭主窗口。或者有更好的解决办法?

    public static List<WaitWindowEntry> waitWindowList = new List<WaitWindowEntry>(); public MainWindow() { InitializeComponent(); isCloseAllWindows(); } private void isCloseAllWindows() { new Thread(()=> { while (true) { for (int i = 0; i < waitWindowList.Count();) { if (waitWindowList[i].isClose == true) { waitWindowList.RemoveAt(i); } else { i++; } } } }); } int i = 1; private void button_Click(object sender, RoutedEventArgs e) { WaitWindowEntry a1 = new WaitWindowEntry(); a1.windowEntry = new WaitWindow(i); a1.Id = i; a1.isClose = false; a1.windowEntry.ShowInTaskbar = false; a1.windowEntry.Show(); waitWindowList.Add(a1);

    i++; } private void button1_Click(object sender, RoutedEventArgs e) { MessageBox.Show("还有"+waitWindowList.Count+"个"); }


    public class WaitWindowEntry
        {
    
            public WaitWindow windowEntry { set; get; }
            public int Id { set; get; }
    
            public bool isClose { set; get; }
    
        }
    public WaitWindow(int k)
            {
                InitializeComponent();
                textBlock.Text = "任务" + k + "进行中,请耐心等待";
                Task.Run(() => {
    
                    for (int i = 0; i < 5; i++)
                    {
                        Thread.Sleep(1000);  //模拟数据库添加操作
                    }
                    System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                    {
                        foreach(var i in MainWindow.waitWindowList)
                        {
                            if (i.Id == k)
                            {
                                i.isClose = true;
                                this.Close();
                            }
                        }
                        
                    }));
    
                });
            }
        }


    我试过以上方法,用集合存窗口,并标记,然后发现似乎有问题,count属性不会减少,只会增加

    怎么判断WaitWindow类型的窗口全部都处于关闭状态了?或者判断全部的子窗体是否都处于关闭状态?或者有更好的方法处理这个问题?








    2017年3月22日 6:53

答案


  • Hi 便携式家园,

    请参考下面的设计。代码供你参考

    主窗体:

      public List<WaitWindowEntry> waitWindowList = new List<WaitWindowEntry>();
    
            private void button_Click(object sender, RoutedEventArgs e)
            {
                WaitWindowEntry a1 = new WaitWindowEntry();
                a1.windowEntry = new Window1(1);
                a1.windowEntry.Show();
                a1.Id = 1;
                a1.isClose = false;
                waitWindowList.Add(a1);
    
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show(waitWindowList.Count.ToString());
            }
    
        public class WaitWindowEntry
        {
            public Window1 windowEntry { set; get; }
            public int Id { set; get; }
            public bool isClose { set; get; }
    
        }

    弹出窗体:

     public partial class Window1 : Window
        {
            //主窗体
            Windowdrop parentwindo = null;
            public Window1()
            {
                InitializeComponent();
            }
    
            public Window1(int i)
            {
                InitializeComponent();
                foreach (Window window in Application.Current.Windows.OfType<Windowdrop>())
                {
                    //
                    parentwindo = (Windowdrop)window;
                    break;
                }
                   
            }
    
            private void Window_Closed(object sender, EventArgs e)
            {
                foreach (var a in parentwindo.waitWindowList)
                {
                    if (a.windowEntry == this)
                    {
                        a.isClose = true;
                        parentwindo.waitWindowList.Remove(a);
                        break;
                    }
                }
                return;
            }
        }
    

    Best Regards,

    Yohann Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年3月23日 6:42
    版主

全部回复

  • “就是用户可能会在一段时间内重复做出包含"向数据库添加数据的"操作。” 操作数据成功后,应该要跳转页面,关闭窗体或是其它的操作,操作失败后才停留在原来的窗体。如果允许重复增加数据(停留在原来的模式),则需要做出一些代码处理以允许数据重复。

    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2017年3月22日 9:59
  • “就是用户可能会在一段时间内重复做出包含"向数据库添加数据的"操作。” 操作数据成功后,应该要跳转页面,关闭窗体或是其它的操作,操作失败后才停留在原来的窗体。如果允许重复增加数据(停留在原来的模式),则需要做出一些代码处理以允许数据重复。

    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    我说的这种操作,是类似{用户执行复制大文件的指令,开启一个复制窗口,该复制过程未完成,然后用户又执行新的复制指令,开启新复制窗口等}这样的行为形式,只不过这个行为在我的项目中的形式是向数据库添加数据。数据的重复性由数据库自身来解决,我担心的是,用户手贱关闭主窗口所造成的的问题
    2017年3月22日 11:17

  • Hi 便携式家园,

    如果要做不断“向数据库添加大量数据的"操作”, 可以考虑使用事务来处理, 一次添加数据的操作要么成功,要么失败。 为了防止UI的卡死,可以使用多线程的来处理,使用同步的方式,事务1执行完再去执行事务2。也可以使用禁用按钮的方式,在一次操作完成之前将按钮IsEnabled设置为False来防止用户多次点击。

    >> 怎么判断某个类型的子窗体是否全部都关闭了

    可以使用一个全局的集合来保存你创建的子窗体,每个子窗体中也定义一个完成操作的变量,创建一个子窗体就添加到这个集合,关闭一个子窗体就从集合移除这个子窗体(关闭之前检查每个子窗体的任务状态),在程序关闭的时候判断这个集合是不是空才可以关闭整个程序。


    Best Regards,

    Yohann Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年3月23日 1:55
    版主

  • Hi 便携式家园,

    如果要做不断“向数据库添加大量数据的"操作”, 可以考虑使用事务来处理, 一次添加数据的操作要么成功,要么失败。 为了防止UI的卡死,可以使用多线程的来处理,使用同步的方式,事务1执行完再去执行事务2。也可以使用禁用按钮的方式,在一次操作完成之前将按钮IsEnabled设置为False来防止用户多次点击。

    >> 怎么判断某个类型的子窗体是否全部都关闭了

    可以使用一个全局的集合来保存你创建的子窗体,每个子窗体中也定义一个完成操作的变量,创建一个子窗体就添加到这个集合,关闭一个子窗体就从集合移除这个子窗体(关闭之前检查每个子窗体的任务状态),在程序关闭的时候判断这个集合是不是空才可以关闭整个程序。


    Best Regards,

    Yohann Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    这种方式也是我正在设计的,不过我正面临的问题就是,程序如何知道窗口关闭了,而且是哪个窗口关闭了?另外楼顶更新了问题代码
    2017年3月23日 5:01

  • Hi 便携式家园,

    请参考下面的设计。代码供你参考

    主窗体:

      public List<WaitWindowEntry> waitWindowList = new List<WaitWindowEntry>();
    
            private void button_Click(object sender, RoutedEventArgs e)
            {
                WaitWindowEntry a1 = new WaitWindowEntry();
                a1.windowEntry = new Window1(1);
                a1.windowEntry.Show();
                a1.Id = 1;
                a1.isClose = false;
                waitWindowList.Add(a1);
    
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show(waitWindowList.Count.ToString());
            }
    
        public class WaitWindowEntry
        {
            public Window1 windowEntry { set; get; }
            public int Id { set; get; }
            public bool isClose { set; get; }
    
        }

    弹出窗体:

     public partial class Window1 : Window
        {
            //主窗体
            Windowdrop parentwindo = null;
            public Window1()
            {
                InitializeComponent();
            }
    
            public Window1(int i)
            {
                InitializeComponent();
                foreach (Window window in Application.Current.Windows.OfType<Windowdrop>())
                {
                    //
                    parentwindo = (Windowdrop)window;
                    break;
                }
                   
            }
    
            private void Window_Closed(object sender, EventArgs e)
            {
                foreach (var a in parentwindo.waitWindowList)
                {
                    if (a.windowEntry == this)
                    {
                        a.isClose = true;
                        parentwindo.waitWindowList.Remove(a);
                        break;
                    }
                }
                return;
            }
        }
    

    Best Regards,

    Yohann Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年3月23日 6:42
    版主