मुख्य विंडो बंद करते समय WPF ऐप बंद नहीं होता है


82

मैं विजुअल स्टूडियो में WinForms प्रोग्रामिंग के लिए उपयोग किया जाता हूं, लेकिन मैं WPF को एक कोशिश देना चाहता था।

मैंने अपने प्रोजेक्ट में एक और विंडो जोड़ी, जिसका नाम Window01 है। मुख्य विंडो को मेनविंडो कहा जाता है। निर्माता से पहले public MainWindow()मैं Window01 घोषित करता हूं:

Window01 w1;

अब मैं इस विंडो को तुरंत इन:

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

मेरे पास एक बटन है जहाँ खिड़की दिखाई जाती है w1.ShowDialog();:।

यहां 'मज़ेदार' बात यह है कि अगर मैं एप्लिकेशन शुरू करता हूं (डिबगिंग के साथ) और इसके कुछ सेकंड बाद बाहर निकलें (मैं एप्लिकेशन में कुछ भी नहीं करता हूं), विजुअल स्टूडियो डिबगिंग को बंद नहीं करता है जैसे कि अनुप्रयोग है अभी भी दौड़ रहा है।

अगर मैं लाइन w1 = new Window01();को बटन क्लिक विधि पर ले जाता हूं , तो बस ऊपर का अर्थ है ShowDialog(), विजुअल स्टूडियो ठीक से व्यवहार कर रहा है - अर्थात, जब मैं एप्लिकेशन से बाहर निकलता हूं तो डिबगिंग बंद हो जाती है।

यह अजीब व्यवहार क्यों?

जवाबों:


138

अपने में MainWindow.xaml.cs, ऐसा करने का प्रयास करें:

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

    Application.Current.Shutdown();
}

इस लिंक के अनुसार, आप ShutdownModeXAML में भी सेट कर सकते हैं :

http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx

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

अनुप्रयोग केवल तभी बंद हो जाता है जब Shutdownविधि Applicationको बुलाया जाता है। शट डाउन ShutdownModeसंपत्ति के मूल्य के अनुसार, स्पष्ट या स्पष्ट रूप से हो सकता है ।

यदि आप Windows प्रेजेंटेशन फ़ाउंडेशन (WPF) में सेट ShutdownModeकरते हैं OnLastWindowClose, तो किसी अनुप्रयोग में अंतिम विंडो बंद होने पर शटडाउन को स्पष्ट रूप से कॉल किया जाता है, भले ही कोई भी वर्तमान में त्वरित विंडो मुख्य विंडो के रूप में सेट की गई हों (देखें मेनविन्डो)

एक ShutdownModeके OnMainWindowCloseकारणों परोक्ष शटडाउन कॉल करने के लिए जब MainWindow बंद है, भले ही अन्य विंडो वर्तमान में खुले हैं WPF।

कुछ अनुप्रयोगों का जीवनकाल उस समय पर निर्भर नहीं हो सकता है जब मुख्य विंडो या अंतिम विंडो बंद हो जाती है, या हो सकता है कि वह खिड़कियों पर निर्भर न हो। इन परिदृश्यों के लिए आपको ShutdownModeसंपत्ति सेट करने की OnExplicitShutdownआवश्यकता होती है, जिसके Shutdownलिए एप्लिकेशन को रोकने के लिए एक स्पष्ट विधि कॉल की आवश्यकता होती है । अन्यथा, अनुप्रयोग पृष्ठभूमि में चल रहा है।

ShutdownMode कोड से XAML या प्रोग्रामेटिक रूप से घोषित किया जा सकता है।

यह संपत्ति केवल उस थ्रेड से उपलब्ध है जिसने Applicationऑब्जेक्ट बनाया है ।


आपके मामले में, ऐप बंद नहीं हो रहा है क्योंकि आप शायद डिफ़ॉल्ट का उपयोग कर रहे हैं OnLastWindowClose:

यदि आप सेट ShutdownModeकरते हैं OnLastWindowClose, तो किसी एप्लिकेशन में अंतिम विंडो बंद होने पर WPF स्पष्ट रूप से शटडाउन को कॉल करता है, भले ही कोई भी वर्तमान में तत्काल विंडो मुख्य विंडो के रूप में सेट हो (देखें MainWindow)।

चूंकि आप एक नई विंडो खोल रहे हैं, और इसे बंद नहीं कर रहे हैं, इसलिए शटडाउन को कॉल नहीं किया जाता है।


1
यह नोट करना महत्वपूर्ण है कि ओवरराइड फ़ंक्शन सबसे अच्छा है यदि आपने कुछ कार्यों को करने के लिए किसी अन्य थ्रेड को त्वरित किया है। शटडाउन फ़ंक्शन में थ्रेड्स को बंद करने से पहले बंद कर दें। अन्यथा थ्रेड्स जीवित रहते हैं और ऐप कभी भी सही मायने में बाहर नहीं निकलता है।
weezma2004

मुझे यकीन नहीं है, अगर इसका एक अच्छा विचार किसी एप्लिकेशन को बंद करने के लिए है, केवल इसलिए कि मेनविंडो बंद है। यह भी संभव है, कि पृष्ठभूमि की प्रक्रिया डीबी को बचाने, लॉग में लिखने, कैशिंग चीजें, उपकरणों को डिस्कनेक्ट करने आदि जैसे कुछ करने की कोशिश कर रही है ... इस बिंदु पर, मैं उस समस्या को ढूंढूंगा जो एप्लिकेशन को बंद कर देता है और इसे ठीक कर देता है। हमेशा अपने एप्लिकेशन को जीवनचक्र में व्यवस्थित करें। Application.Current.Shutdown()टास्कबार पर प्रक्रिया को पूरा करने की तरह तुरंत आवेदन को बंद कर देगा। यह किसी को गोली मारने जैसा है, इससे पहले कि वह अपना आखिरी शब्द कहे :) .. मैं सिफारिश नहीं करूंगा।
Vural

35

मुझे खुशी है कि आपको आपका जवाब मिल गया, लेकिन दूसरों की खातिर मैं आपके सवाल का जवाब दूंगा-साथ ही कुछ जानकारी भी जोड़ने के लिए।


चरण 1

सबसे पहले, यदि आप चाहते हैं कि आपका प्रोग्राम मुख्य विंडो बंद होने पर बाहर निकलें, तो आपको निर्दिष्ट करने की आवश्यकता है, क्योंकि यह WinForms नहीं है जहां यह व्यवहार डिफ़ॉल्ट है।

(अंतिम विंडो बंद होने पर WPF में डिफ़ॉल्ट)

कोड में

अपने प्रवेश बिंदु पर अपने आवेदन के उदाहरण पर जाएं (वीएस 2012 के डब्ल्यूपीएफ कार्यक्रम में डिफ़ॉल्ट के अंदर नेस्टेड है App.xaml, इसलिए इसके अंदर जाएं App.xaml.csऔर एक निर्माणकर्ता पर नेविगेट करें और बनाएं)।

निर्माता में निर्दिष्ट है कि आपके Applicationके ShutdownModeहोना चाहिए ShutdownModeOnLastWindowClose

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

XAML में

अपने पर जाएं App.xamlफ़ाइल कि वी.एस. 2012 डिफ़ॉल्ट रूप से बनाया (या इसे स्वयं बनाने) जड़ एक है Application, जो आपके अंदर निर्दिष्ट Applicationकी ShutdownModeहोना चाहिए ShutdownModeOnLastWindowClose

<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 में किया था, और इसे निर्दिष्ट करें ApplicationMainWindowआपका मूल्य है Window:

MainWindow = mainWindow;

XAML में

ApplicationXAML पर जाएं जैसा आपने चरण 1 में किया था, और इसे निर्दिष्ट करें ApplicationMainWindowआपका मूल्य है Window:

MainWindow = "mainWindow";

विकल्प

मुझे नहीं लगता कि यह सबसे अच्छा तरीका है, सिर्फ इसलिए कि WPF आपको ऐसा नहीं करना चाहता है (इसलिए इसमें Application's ShutdownMode) है, लेकिन आप किसी ईवेंट का उपयोग कर सकते हैं / किसी ईवेंट विधि (OnEventHappened) को ओवरराइड कर सकते हैं।

MainWindow के कोड-पीछे फ़ाइल में जाएं और जोड़ें:

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

        App.Current.Shutdown();
    }

3
आपका उत्तर बेहतर है, फिर वह जो चिह्नित है।
सीकर

सेट: मैं आमतौर पर यह इस तरह से करना MainWindowमुख्य विंडो के उदाहरण, स्थापित करने के लिए ShutdownModeकरने के लिए ShutdownMode.OnMainWindowClose, कॉल MainWindow.Show()करने के लिए कॉलबैक में Startupहोने की स्थिति App। यह सबसे न्यूनतम समाधान है, जो WPF के साथ कम से कम .NET कोर 3 में अपेक्षित रूप से काम करता है।
TorbenJ

11

क्योंकि WPF एप्लिकेशन में डिफ़ॉल्ट शटडाउन मोड OnLastWindowClose है, जिसका अर्थ है कि अंतिम विंडो बंद होने पर एप्लिकेशन बंद हो जाता है।

जब आप एक नई विंडो ऑब्जेक्ट को इंस्टेंट करते हैं, तो यह एप्लिकेशन में विंडोज़ की सूची में स्वचालित रूप से जुड़ जाता है । तो, समस्या यह थी कि आपका अनुप्रयोग शुरू होने पर दो विंडो बना रहा था - मेनविंडो और अभी तक नहीं दिखाया गया Window01 - और यदि आपने केवल MainWindow को बंद कर दिया, तो Window01 आपके एप्लिकेशन को चालू रखेगा।

आम तौर पर, आप उसी तरीके से एक विंडो ऑब्जेक्ट बनाएंगे जो उसके शो डिडियोग्ल को कॉल करने जा रहा है, और आप प्रत्येक बार डायलॉग दिखाए जाने पर एक नई विंडो ऑब्जेक्ट बनाएंगे।


2

जब मैंने कुछ और खोजा तो मैं इस सवाल पर अड़ गया और मुझे आश्चर्य हुआ कि मैं किसी प्रस्तावित उत्तर के बारे में नहीं देख सकता 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 आवेदन के दृश्य में काफी उपयोगी होता है जब आप दूर नहीं जानने तुम कहाँ instantiated कर दिया है दृश्य पेड़ नीचे, यह किसी भी आपूर्ति से बुलाया जा सकता है FrameWorkतत्व (जैसे UserContol, Button, Page)। जाहिर है अगर आपके पास खिड़की का सीधा संदर्भ है तो उस या यहां तक ​​कि उपयोग करें Application.Current.MainWindow

यह काफी शक्तिशाली संबंध है जिसमें कई उपयोगी लाभ हैं जिन्हें आप शुरू करने के लिए महसूस नहीं कर सकते हैं (यह मानते हुए कि आपने इन रिश्तों से बचने के लिए विशेष रूप से अलग खिड़कियों को कोडित नहीं किया है)।

अगर हम आपकी मुख्य खिड़की MainWindowऔर दूसरी खिड़की को AdditionalWindowभी कहते हैं ...।

  1. MainWindowवसीयत को कम से कम करना भी होगाAdditionalWindow
  2. MainWindowजीर्णोद्धार भी बहाल करेंगेAdditionalWindow
  3. समापन बंद MainWindowहो जाएगा AdditionalWindow, लेकिन समापन बंद AdditionalWindowनहीं होगाMainWindow
  4. AdditioanlWindowके तहत "खो" कभी नहीं मिलेगा MainWindow, यानी AddditionalWindowहमेशा MainWindowz- क्रम में ऊपर दिखाता है अगर आप 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();
        }        
    }

1

उपरोक्त में से कोई भी मेरे लिए काम नहीं करता है, हो सकता है क्योंकि हमारी परियोजना प्रिज्म का उपयोग करती है। तो App.XAML.cs में इसका उपयोग करके समाप्त हुआ

    protected override void OnExit(ExitEventArgs e)
    {
        base.OnExit(e);
        Process.GetCurrentProcess().Kill();
    }

0

ऐसा लगता है कि जब मैं एक डायलॉग बॉक्स के रूप में अभिनय करने के लिए दूसरी विंडो बनाता हूं, तो कुछ ऐसा होता है। जब दूसरी विंडो खोली गई और फिर बंद हो गई और फिर मुख्य विंडो बंद हो गई, तो ऐप चालू रहा (पृष्ठभूमि में)। मैंने अपने App.xaml में निम्नलिखित (या पुष्टि) जोड़े:

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

कोई आनंद नहीं है।

तो, मैं अंत में अपने "मेनविन्डो.एक्सैमल" में चला गया और विंडो में एक "क्लोज्ड" प्रॉपर्टी को जोड़ा, जो "मेनविंड_क्लोस्ड" पद्धति में गई, जो निम्न की तरह दिखता है:

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

डिबगर के माध्यम से चल रहा है, यह केवल खिड़की की तरह दिखता है जो दिखाता है कि मैं एक संवाद के रूप में बनाई गई खिड़की है - दूसरे शब्दों में, फ़ॉरच लूप केवल एक खिड़की पाता है - संवाद, मुख्य नहीं।

मेरे पास "this.Close ()" विधि है जो संवाद को बंद कर रही है, और मेरे पास "dlgwin.Close ()" है जो "dlgwin.ShowDialog ()" के बाद आया था, और यह काम नहीं किया। एक भी नहीं "dlgwin = null"।

तो, इस अतिरिक्त सामग्री के बिना वह संवाद क्यों बंद नहीं होगा? ओह अच्छा। यह काम।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.