Как закрыть окно wpf

от admin

WPF MVVM: How to close a window

I have a Button that closes my window when it’s clicked:

That’s fine until I add a Command to the Button i.e.

Now it doesn’t close presumably because I am handling the Command . I can fix this by putting an EventHandler in and calling this.Close() i.e.

but now I have code in my code behind i.e. the method SaveCommand . I am using the MVVM pattern and SaveCommand is the only code in my code behind.

How can I do this differently so as not to use code behind?

22 Answers 22

I just completed a blog post on this very topic. In a nutshell, add an Action property to your ViewModel with get and set accessors. Then define the Action from your View constructor. Finally, invoke your action in the bound command that should close the window.

In the ViewModel:

and in the View constructor:

Finally, in whatever bound command that should close the window, we can simply invoke

This worked for me, seemed like a fairly elegant solution, and saved me a bunch of coding.

Jonathan Shay's user avatar

Very clean and MVVM way is to use InteractionTrigger and CallMethodAction defined in Microsoft.Interactivity.Core

You will need to add a new namespace as below

You will need the Microsoft.Xmal.Behaviours.Wpf assembly and then the below xaml code will work.

You don’t need any code behind or anything else and can also call any other method of Window .

Rajnikant's user avatar

As someone commented, the code I have posted is not MVVM friendly, how about the second solution?

1st, not MVVM solution (I will not delete this as a reference)

2nd, probably better solution: Using attached behaviours

Behaviour Class Something similar to this:

jeuxjeux20's user avatar

I’d personally use a behaviour to do this sort of thing:

You can then attach this to your Window and Button to do the work:

I’ve added Command and CommandParameter here so you can run a command before the Window closes.

Massimiliano Kraus's user avatar

For small apps, I use my own Application Controller for showing, closing and disposing windows and DataContexts. It’s a central point in UI of an application.

It’s something like this:

and their invocations from ViewModels:

Of course you can find some restrictions in my solution. Again: I use it for small projects, and it’s enough. If you’re interested, I can post full code here or somewhere else/

wonea's user avatar

I’ve tried to resolve this issue in some generic, MVVM way, but I always find that I end up unnecessary complex logic. To achieve close behavior I have made an exception from the rule of no code behind and resorted to simply using good ol’ events in code behind:

Although I wish this would be better supported using commands/MVVM, I simply think that there is no simpler and more clear solution than using events.

larsmoa's user avatar

I use the Publish Subscribe pattern for complicated class-dependencies:

ViewModel:

Window:

You can leverage Bizmonger.Patterns to get the MessageBus.

MessageBus

Subscription

There is a useful behavior for this task which doesn’t break MVVM, a Behavior, introduced with Expression Blend 3, to allow the View to hook into commands defined completely within the ViewModel.

Как закрыть окно wpf

Gray Pipe

This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.

Answered by:

Question

Currently I am doing this.Close(); on the window but it does not completely dipose off the reference.

For example if I have a System.Timers.Timer inside the window to update something, it keeps doing that even after the window has been closed.

What is the correct way to dispose this off? Am I supposed to handle the window.Closing event and do a timer.Dispose() there? I see there is no Window.Dispose() in WPF.

EDIT: Also what if a user control is used in the window that contains a timer? How should the user control dispose itself properly on Window.Close()

Answers

public DispatcherTimer dt;
public Window2()
<
InitializeComponent();
NativeMethods.AllocConsole();
Console.WriteLine("start");
dt = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher);
dt.Interval = new TimeSpan(10000000);
dt.Tick += new EventHandler(new EventHandler(dt_Tick));
dt.Start();
>
protected override void OnClosed(EventArgs e)
<
base.OnClosed(e);
dt.Stop();
>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Timers;
namespace CloseWPF_20081209
<
/// < summary >
/// Interaction logic for Window1.xaml
/// </ summary >
public partial class Window1 : Window
<
public Window1()
<
InitializeComponent();
Window2 w = new Window2();
w.Show();
>
>
>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace CloseWPF_20081209
<
public partial class NativeMethods
<
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
>
/// < summary >
/// Interaction logic for Window2.xaml
/// </ summary >
public partial class Window2 : Window
<
public DispatcherTimer dt;
public Window2()
<
InitializeComponent();
NativeMethods.AllocConsole();
Console.WriteLine("start");
dt = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher);
dt.Interval = new TimeSpan(10000000);
dt.Tick += new EventHandler(new EventHandler(dt_Tick));
dt.Start();
>
protected override void OnClosed(EventArgs e)
<
base.OnClosed(e);
dt.Stop();
>
public void dt_Tick(Object sender, EventArgs e)
<
Console.WriteLine(Name + " " + DateTime.Now);
>
>
>
  • Marked as answer by Tao Liang Tuesday, December 9, 2008 9:48 AM

All replies

You don’t manually dispose of any WPF objects, they just get garbage-collected when there are no more references to them. If a window is still alive that usually means you have some reference to that window lying around somewhere in your code.

I wonder if there’s a circular reference at play here. Timers keep the objects alive to which their events are bound. Now this timer should be garbage-collected along with the containing window but if an event is bound to that same window it would be marked as alive, and thus the timer itself as well. but shouldn’t the GC see that the whole circle is isolated?

Anyway, as you guessed you could override OnClosing and just stop the timer there, and perhaps remove the event delegate to be sure. Have you considered using a DispatcherTimer, by the way? That’s the recommended timer for WPF objects though I have no idea if it would behave any differently with regards to closed windows.

WPF MVVM: как закрыть окно

У меня есть Button , который закрывает мое окно при нажатии:

Это нормально, пока я не добавлю Command к Button i.e.

Читать:
Как скрыть пользователя в windows 10

Теперь он не закрывается, предположительно, потому что я обрабатываю Command . Я могу исправить это, поставив EventHandler в и вызывающий this.Close() i.e.

но теперь у меня есть код в моем коде, то есть метод SaveCommand . Я использую шаблон MVVM, а SaveCommand — это единственный код в моем коде.

Как я могу сделать это по-другому, чтобы не использовать код?

19 ответов

Я только что закончил сообщение в блоге по этой теме. Вкратце добавьте свойство Action к вашему ViewModel с помощью get и set accessors. Затем определите Action из вашего конструктора View . Наконец, вызовите свое действие в связанной команде, которая должна закрыть окно.

и в конструкторе View :

Наконец, в любой связанной команде, которая должна закрыть окно, мы можем просто вызвать

Это сработало для меня, показалось довольно элегантным решением и спасло мне кучу кодирования.

К сожалению, отображение окон — это настоящая боль в MVVM, поэтому вам нужно выполнить небольшую работу по созданию инфраструктуры или использовать инфраструктуру MVVM, например Cinch. Если вы хотите потратить время, чтобы сделать это самостоятельно здесь ссылку о том, как Cinch делает это.

Хорошо, что вы пытаетесь сохранить любую логику из представления, но это действительно не конец света, если вы это сделаете. В этом случае это не похоже, что это вызовет слишком много проблем.

Как кто-то прокомментировал, код, который я опубликовал, не совместим с MVVM, как насчет второго решения?

1-е, а не MVVM-решение (я не буду удалять это как ссылку)

2-е, возможно лучшее решение: Использование прикрепленного поведения

Класс поведения Что-то похожее на это:

Я лично использовал бы поведение, чтобы делать такие вещи:

Затем вы можете присоединить это к вашим Window и Button для выполнения работы:

Я добавил здесь Command и CommandParameter , чтобы вы могли запускать команду до закрытия Window .

Очень чистый и MVVM способ использовать InteractionTrigger и CallMethodAction , определенные в Microsoft.Interactivity.Core

Вам нужно будет добавить два пространства имен, как показано ниже

И сборки System.Windows.Interactivity и Microsoft.Expression.Interactions, а затем Ниже код xaml будет работать.

Вам не нужен какой-либо код или что-то еще, а также можно вызвать любой другой метод Window .

Для небольших приложений я использую свой собственный Application Controller для отображения, закрытия и удаления окон и DataContexts. Это центральная точка в пользовательском интерфейсе приложения.

Что-то вроде этого:

и их вызовы из ViewModels:

Конечно, вы можете найти некоторые ограничения в моем решении. Опять же: я использую его для небольших проектов, и этого достаточно. Если вам интересно, я могу разместить полный код здесь или где-то еще/

Я использую шаблон Опубликовать подписку для сложных зависимостей классов:

ViewModel:

Window:

Вы можете использовать Bizmonger.Patterns, чтобы получить MessageBus.

MessageBus

Подписка

Я попытался решить эту проблему на каком-то родовом пути MVVM, но всегда обнаруживаю, что в итоге я оказываю ненужную сложную логику. Чтобы достичь близкого поведения, я сделал исключение из правила отсутствия кода и прибегнул к простому использованию хороших событий в коде:

Хотя я бы хотел, чтобы это лучше поддерживалось с помощью команд /MVVM, я просто думаю, что нет более простого и более четкого решения, чем использование событий.

Существует полезное поведение для этой задачи, которая не нарушает MVVM, Поведение, представленное с помощью Expression Blend 3, чтобы позволить View захватывать команды, полностью определенные в ViewModel.

Это поведение демонстрирует простой способ разрешения ViewModel для управления закрывающими событиями представления в Приложение Model-View-ViewModel.

Это позволяет подключить поведение в вашем представлении (UserControl), которое обеспечит контроль над окном управления, позволяя ViewModel для контроля того, можно ли закрыть окно через стандартные ICommands.

Использование правил, позволяющих ViewModel управлять временем жизни в M-V-VM

http://gallery.expression.microsoft.com/WindowCloseBehavior/

У нас есть свойство name в определении .xaml:

Тогда у нас есть кнопка:

Затем в ViewModel:

Затем, наконец, метод действия:

Я использовал этот код, чтобы закрыть всплывающее окно из приложения.

Я долгое время боролся с этой темой и в конечном итоге пошел с самым простым подходом, который по-прежнему согласуется с MVVM: пусть кнопка выполнит команду, которая выполняет весь тяжелый подъем, и нажимает кнопку Click handler.

XAML

XAML.cs

SaveCommand.cs

Правда, все еще есть код, но в этом нет ничего плохого. И это имеет для меня смысл, с точки зрения ОО, просто сказать, что окно закрывается.

Как я могу выйти из приложения WPF программно?

в течение нескольких лет я использую C# (Windows Forms), я никогда не использовал WPF. Но, теперь я люблю WPF, но я не знаю, как я должен выйти из моего приложения, когда пользователь нажимает на пункт меню Выход из меню Файл.

среди многих других. Ничего не работает.

15 ответов:

  • когда ShutdownMode установлен в OnLastWindowClose.
  • когда ShutdownMode имеет значение OnMainWindowClose.
  • когда пользователь завершает сеанс и событие SessionEnding либо не обрабатывается, либо обрабатывается без отмены.

обратите внимание, что Application.Current.Shutdown(); может быть вызван только из потока, который создал Application «объект», т. е. обычно основной поток.

Если вы действительно нужно, чтобы закрыть вы также можете использовать окружающая среда.Exit (), но это совсем не изящно (больше похоже на завершение процесса).

использовать его следующим образом:

как wuminqi сказал, Application.Current.Shutdown(); является необратимым, и я считаю, что он обычно используется для принудительного закрытия приложения в такие моменты, как когда пользователь выходит из системы или завершает работу Windows.

вместо этого позвоните this.close() в главном окне. Это то же самое, что нажать Alt + F4 или кнопку Закрыть [x]в окне. Это приведет к закрытию всех других принадлежащих окон и в конечном итоге вызовет Application.Current.Shutdown(); пока близко не отмененный. Пожалуйста, смотрите документацию MSDN на закрыть окно.

кроме того, потому что this.close() отменяется вы можете поместить в диалоговом окне подтверждения сохранения изменений в обработчике событий закрытия. Просто сделайте обработчик событий для <Window Closing=». «> , и e.Cancel соответственно. (См. Примечание для получения более подробной информации о том, как это сделать.)

при необходимости используйте любое из следующих средств:

1.

2.

прежде всего методы будут вызывать closing event на Window класс и выполнение может остановиться в какой-то момент (причина обычно приложения ставят диалоги, как ‘вы уверены?- иливы хотите сохранить данные перед закрытием?‘, прежде чем окно будет полностью закрыто)

3. но если вы хотите завершить приложение без какого-либо предупреждения немедленно. Используйте ниже

Это должно сделать трюк:

Если вам интересно, вот некоторые дополнительные материалы, которые я нашел полезными:

подробная информация о применении.Ток

жизненный цикл приложения WPF

Похожие статьи