c# - WPF التطبيق لا تغلق عند إغلاق النافذة الرئيسية




visual-studio-2010 window (4)

أنا معتاد على WinForms البرمجة في Visual Studio ، ولكن كنت أرغب في إعطاء WPF محاولة.

أضفت نافذة أخرى إلى مشروعي ، تسمى Window01. يسمى الإطار الرئيسي MainWindow. قبل المصمم العام MainWindow public MainWindow() أعلن Window01:

Window01 w1;

الآن أقوم بإنشاء هذه النافذة في:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    w1 = new Window01();            
}

لدي زر تظهر فيه النافذة: w1.ShowDialog(); .

الشيء "المضحك" هنا هو حقيقة أنه في حالة بدء التطبيق (مع تصحيح الأخطاء) والخروج منه بعد ثوانٍ قليلة (لا أفعل أي شيء في التطبيق) ، لا يتوقف Visual Studio عن تصحيح الأخطاء كما لو كان التطبيق لا يزال قيد التشغيل.

إذا قمت بنقل السطر w1 = new Window01(); إلى طريقة النقر فوق الزر ، وهذا يعني فقط فوق ShowDialog() ، يعمل Visual Studio بشكل صحيح - وهذا يعني أن التصحيح يتوقف عند الخروج من التطبيق.

لماذا هذا السلوك الغريب؟


أنا سعيد لأنك حصلت على إجابتك ولكن من أجل الآخرين سأجيب عن سؤالك بشكل جيد لإضافة بعض المعلومات.

الخطوة 1

أولاً ، إذا كنت ترغب في إنهاء البرنامج عند إغلاق الإطار الرئيسي ، يجب تحديده ، نظرًا لأن هذا ليس WinForms حيث يكون هذا السلوك افتراضيًا.

(الافتراضي في WPF هو عند إغلاق الإطار الأخير)

في الكود

انتقل إلى مثيل التطبيق الخاص بك في نقطة الإدخال (برنامج WPF في VS 2012 الافتراضي هو المتداخل داخل App.xaml ، لذلك انتقل داخله وانتقل إلى App.xaml.cs بإنشاء مُنشئ).

في المنشئ تحديد أن http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx Application الخاص بك ينبغي أن يكون ShutdownMode . OnLastWindowClose .

    public App()
    {
        ShutdownMode = ShutdownMode.OnLastWindowClose;
    }

في XAML

انتقل إلى ملف App.xaml الذي أنشأته VS 2012 بشكل افتراضي (أو App.xaml بنفسك) الجذر هو أحد Application ، حدد داخل Application http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx الخاص بك يجب أن يكون ShutdownMode . OnLastWindowClose .

<Application x:Class="WpfApplication27.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml"
         ShutdownMode="OnMainWindowClose">

إذا نجحت ، انتهيت ؛ يمكنك التوقف عن القراءة.

الخطوة 2

إذا لم يعمل ما سبق (أعتقد أنك كتبت تطبيق WPF من الصفر) ، فمن المحتمل أن النافذة الرئيسية غير معروفة للتطبيق كنافذة رئيسية. لذلك حدد ذلك جيدا.

في الكود

انتقل إلى مُنشئ التطبيق كما فعلت في الخطوة 1 ، وحدد هذا Application . قيمة MainWindow هي Window :

MainWindow = mainWindow;

في XAML

انتقل إلى Application XAML كما فعلت في الخطوة 1 ، وحدد ذلك Application . قيمة MainWindow هي Window :

MainWindow = "mainWindow";

لبديل

لا أعتقد أن هذا هو الأسلوب الأفضل ، فقط لأن WPF لا تريد منك القيام بذلك (لذلك يوجد http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx Application ) ، ولكن يمكنك فقط استخدام حدث / تجاوز أسلوب الحدث (OnEventHappened).

انتقل إلى ملف التعليمات البرمجية خلف MainWindow وإضافة:

    protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);

        App.Current.Shutdown();
    }

تعثرت عبر هذا السؤال عند البحث عن شيء آخر وفوجئت بأنني لم أتمكن من رؤية أي من الإجابات المقترحة التي تشير إلى Window.Owner .

    {
       var newWindow = new AdditionalWindow();
       newWindow.Owner = Window.GetWindow(this);

       // then later on show the window with Show() or ShowDialog()
    }

يعتبر الاتصال بـ Window.GetWindow(this) مفيدًا تمامًا في طريقة عرض تطبيق MVVM عندما تكون بعيدًا عن الشجرة المرئية التي لا تعرف مكان تثبيتها ، يمكن أن يطلق عليها عن طريق توفير أي عنصر FrameWork (مثل UserContol أو Button أو Page ). من الواضح إذا كان لديك إشارة مباشرة إلى النافذة ثم استخدم هذا أو حتى Application.Current.MainWindow .

هذه علاقة قوية للغاية تحتوي على عدد من الفوائد المفيدة التي قد لا تدرك أنها تبدأ (بافتراض أنك لم ترميز نوافذ منفصلة لتجنب هذه العلاقات).

إذا MainWindow بك MainWindow النافذة الرئيسية والنافذة الثانية كما AdditionalWindow ثم ....

  1. تصغير MainWindow سوف أيضاً تصغير MainWindow
  2. استعادة MainWindow أيضاً استعادة MainWindow
  3. إغلاق إغلاق MainWindow سوف MainWindow ولكن إغلاق MainWindow إغلاق MainWindow
  4. لن تحصل على AdditioanlWindow أبدًا "ضائعة" تحت MainWindow ، أي AddditionalWindow يظهر دائمًا فوق MainWindow في الترتيب z إذا استخدمت Show() لعرضه (مفيد جدًا!)

شيء واحد أن نلاحظ على الرغم من ذلك ، إذا كان لديك هذه العلاقة ، ثم لا يتم استدعاء الحدث Closing على AdditionalWindow ، لذلك عليك أن تتكرر يدويا عبر مجموعة OwnedWindows . على سبيل المثال ، قم بإنشاء طريقة للاتصال بكل نافذة عبر واجهة جديدة أو طريقة أساسية.

    private void MainWindow_OnClosing(object sender, CancelEventArgs e)
    {
        foreach (var window in OwnedWindows)
        {
            var win = window as ICanCancelClosing;  // a new interface you have to create
            e.Cancel |= win.DoYouWantToCancelClosing();
        }        
    }

لأن http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx الافتراضي في تطبيق WPF هو OnLastWindowClose ، مما يعني توقف التطبيق عند إغلاق النافذة الأخيرة.

عند إنشاء كائن إطار جديد ، تتم إضافته تلقائيًا إلى قائمة الإطارات في التطبيق. لذا ، كانت المشكلة أن التطبيق الخاص بك كان يقوم بإنشاء نافذتين عند بدء التشغيل - MainWindow و Window01 غير الموضح بعد - وإذا قمت فقط بإغلاق MainWindow ، فإن Window01 سيبقي التطبيق قيد التشغيل.

عادة ، ستقوم بإنشاء كائن نافذة بنفس الطريقة التي ستقوم باستدعاء ShowDialog الخاص بها ، وستقوم بإنشاء كائن نافذة جديد في كل مرة يظهر فيها مربع الحوار.


يبدو وكأنه شيء صادفته عندما أنشأت نافذة ثانية للتصرف كمربع حوار. عندما فتحت النافذة الثانية ثم أغلقت ثم أغلقت النافذة الرئيسية ، استمر تشغيل التطبيق (في الخلفية). أضفت (أو أكدت) ما يلي في App.xaml:

<Application x:Class="XXXXXXX.App"
             ...  
             StartupUri="MainWindow.xaml"
             ShutdownMode="OnMainWindowClose">
    <Application.MainWindow >
        <NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
    </Application.MainWindow>

لا فرح.

لذلك ، ذهبت أخيرا في بلدي "MainWindow.xaml" وأضاف خاصية "مغلقة" إلى النافذة التي ذهبت إلى أسلوب "MainWind_Closed" الذي يشبه ما يلي:

 private void MainWind_Closed(object sender, EventArgs e)
        {
            foreach ( Window w in App.Current.Windows )
            {
                if (w.DataContext != this)
                    w.Close();
            }
        }

من خلال تشغيل المصحح ، يبدو أن النافذة الوحيدة التي تظهر هي النافذة التي قمت بإنشائها كمربع حوار - وبعبارة أخرى ، فإن حلقة foreach تعثر فقط على نافذة واحدة - الحوار ، وليس الرئيسي.

كان لي "this.Close ()" تعمل في الأسلوب الذي أغلق الحوار ، وكان لي "dlgwin.Close ()" التي جاءت بعد "dlgwin.ShowDialog ()" ، والتي لم تنجح. ولا حتى "dlgwin = null".

لذا ، لماذا لا يغلق هذا الحوار بدون هذه الأشياء الإضافية؟ اوه حسناً. هذا يعمل.







window