Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/14: Рейтинг темы: голосов - 14, средняя оценка - 4.86
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407

Управление окнами MVVM

01.02.2024, 16:17. Показов 2965. Ответов 33
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня есть сервис открытия/закрытия окон, я передаю туда тип VM, не передаю саму VM так как контекст всем окнам уже присвоен через локатор.
Сервис открытия/закрытия окон:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public interface IWindowFactory
{
    void CreateNewWindow(Type type);
    void CloseWindow(Type type);
}
public class ProductionWindowFactory : IWindowFactory
{
 
    #region Implementation of INewWindowFactory
 
    bool isWindowOpen = false;
 
    public void CreateNewWindow(Type type)
    {
        switch (type.Name)
        {
            case "ViewModelMain":
                isWindowOpen = false;
 
                foreach (Window w in Application.Current.Windows)
                {
                    if (w is MainWindow)
                    {
                        isWindowOpen = true;
                        w.Activate();
                    }
                }
 
                if (!isWindowOpen)
                {
                    Window settingsWindow = new MainWindow();
                    settingsWindow.Owner = App.Current.MainWindow;
                    settingsWindow.Show();
                }
                break;
            case "ViewModelLogin":
                isWindowOpen = false;
 
                foreach (Window w in Application.Current.Windows)
                {
                    if (w is LoginWindow)
                    {
                        isWindowOpen = true;
                        w.Activate();
                    }
                }
 
                if (!isWindowOpen)
                {
                    Window aboutProgramWindow = new LoginWindow();
                    aboutProgramWindow.Owner = App.Current.MainWindow;
                    aboutProgramWindow.Show();
                }
                break;
        }
    }
 
    public void CloseWindow(Type type)
    {
        switch (type.Name)
        {
            case "ViewModelMain":
                isWindowOpen = false;
 
                foreach (Window w in Application.Current.Windows)
                {
                    if (w is MainWindow)
                    {
                        w.Close();
                    }
                }
                break;
            case "ViewModelLogin":
                isWindowOpen = false;
 
                foreach (Window w in Application.Current.Windows)
                {
                    if (w is LoginWindow)
                    {
                        w.Close();
                    }
                }
                break;
        }
    }
    #endregion
}

Локатор:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Locator
{
    private IServiceProvider _serviceProvider;
 
    public ViewModelMain MainVM { get; set; }
    public ViewModelLogin LoginVM { get; set; }
 
    public Locator()
    {
        ConfigureServices();
        MainVM = _serviceProvider.GetService<ViewModelMain>();
        LoginVM = _serviceProvider.GetService<ViewModelLogin>();
    }
    private void ConfigureServices()
    {
        var serviceCollection = new ServiceCollection();
 
        serviceCollection
            .AddTransient<ViewModelMain>()
            .AddTransient<ViewModelLogin>()
            .AddSingleton<IModelService, ModelService>()
            .AddSingleton<IMessageBoxService, MessageBoxService>()
            .AddSingleton<IWindowFactory, ProductionWindowFactory>();
 
        _serviceProvider = serviceCollection.BuildServiceProvider();
    }
}

Вопрос откуда должны вообще закрываться/открываться окна? Я везде где читал написано было, что нужно из VM окна открывать, а как по мне это удобней из модели это делать. Вот например Проверка авторизации: Мне после того как я проверил логин/пароль успешно(это у меня в модели происходит) нужно сообщить об этом в VM логина или в главную VM и оттуда открыть главное окно(так же закрыть окно логина) или прям в модели это нужно сделать без сообщения c VM?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.02.2024, 16:17
Ответы с готовыми решениями:

MVVM работа с окнами
Подскажите пожалуйста в чем и где моя ошибка? В главном окне через viewmodel подключаюсь к локальной базе, по нажатию на кнопку меню, через...

Пример переключения между окнами WPF MVVM
Здравствуйте. Изучаю как можно переходить между окнами в wpf в рамках MVVM. Изучаю данный пример: ...

Передача данных между окнами в рамках паттерна MVVM
Доброго времени суток, уважаемые форумчане! Я абсолютный новичок в программировании, который пытается освоить, хотя бы в небольшой...

33
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
05.02.2024, 17:28
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от firnen_dragon Посмотреть сообщение
и при закрытии окна логина будет закрываться все приложение
Не будет. В этом режиме нужно вызывать Shutdown руками, что вы и делаете в своём методе. Оставьте по умолчанию, оно сработает либо при закрытии последнего окна, либо при ручном вызове.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
05.02.2024, 17:43  [ТС]
Andrey-MSK, Мне тогда надо, еще подписаться на Closing в MainWindow и там тоже Shutdown вызывать, потому-что сейчас при закрытии главного приложение продолжает работать. Больше кода как-будто бы

Добавлено через 11 минут
Ну или я что-то не так понял
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
05.02.2024, 18:12
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Подозреваю, что тот, который по умолчанию, потому что кроме этого у меня в xaml App ничего нету.
По умолчанию я не помню какой.
И возможно он даже меняется где-то в настройках Студии.
Выберите "по закрытию всех Окон" или "после Основного Окна".

Добавлено через 3 минуты
Цитата Сообщение от firnen_dragon Посмотреть сообщение
потому-что сейчас при закрытии главного приложение продолжает работать. Больше кода как-будто бы
Много Окон или только одно?
Если много, то может есть какое-то скрытое?
Установите режим на закрытие приложения после закрытия основного Окна.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
06.02.2024, 10:47  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
По умолчанию я не помню какой.
По умолчанию - OnLastWindowClose
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Много Окон или только одно?
Если много, то может есть какое-то скрытое?
Я имел ввиду, что закрытие MainWindow не закрывает приложение, если использовать OnExplicitShutdown как сказал Andrey-MSK, там нужно еще дополнительно подписываться на Closing в MainWindow и там вызывать Shutdown, а так-то в итоге я оставил просто OnLastWindowClose и все работает отлично, всем спасибо за объяснения
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
06.02.2024, 12:19
Цитата Сообщение от firnen_dragon Посмотреть сообщение
По умолчанию - OnLastWindowClose
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Я имел ввиду, что закрытие MainWindow не закрывает приложение, если использовать OnExplicitShutdown как сказал Andrey-MSK, там нужно еще дополнительно подписываться на Closing в MainWindow и там вызывать Shutdown
Я бы сначала разобрался почему при закрытии всех окон приложение не закрывается.
Возможно, это признак какого-то бага, который может проявиться ещё и по другому.
Нужно выявить и устранить баг, а не маскировать его "аварийным стопом".
2
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
06.02.2024, 12:24
firnen_dragon, У вас случаем в App.xaml.cs этот метод не переопределён?
C#
1
2
3
4
5
6
7
8
9
protected override void OnExit(ExitEventArgs e)
{
    IBackgroundTaskQueue _taskQueue
        = Current.Services.GetService<IBackgroundTaskQueue>();
 
    _taskQueue.Stop();
 
    base.OnExit(e);
}
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
06.02.2024, 17:35  [ТС]
Элд Хасп, Давайте опишу поведение при каждом из режимов при условии, что код в App я не меняю, потому что мне кажется у нас произошло недопонимание, при OnExplicitShutdown у меня и не должно выключаться приложение когда я закрыл все окно, только, если я явно не скажу приложению выключиться после того как закроется главное окно. И так:

ShutdownMode="OnExplicitShutdown":
- При закрытии окна логина на X: приложение закрывается
- При закрытии главного окна(больше не остается никаких окон) на X после авторизации: приложение не закрывается
ShutdownMode="OnLastWindowClose":
- При закрытии окна логина на X: приложение закрывается
- При закрытии главного окна(больше не остается никаких окон) на X после авторизации: приложение закрывается
ShutdownMode="OnMainWindowClose":
- При закрытии окна логина на X: приложение закрывается
- При закрытии главного окна(больше не остается никаких окон) на X после авторизации: приложение закрывается

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Много Окон или только одно?
Окна еще есть, но они не задействованы нигде, сервис создания окон я тоже не использую нигде
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
У вас случаем в App.xaml.cs этот метод не переопределён?
Не переопределен

На всякий случай кину весь код из App(кроме как в App я нигде с окнами не работаю):
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public partial class App : Application
{
    MainWindow mainWindow;
    LoginWindow loginWindow;
    private Locator locator;
 
    public App()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
    }
 
    protected void OnStartup(object sender, StartupEventArgs e)
    {
        locator = (Locator)Resources["locator"];
        MainWindow = mainWindow = new MainWindow();
        loginWindow = new LoginWindow();
        loginWindow.Closing += LoginWindow_Closing;
        locator.LoginVM.PropertyChanged += LoginVM_PropertyChanged;
        loginWindow.Show();
    }
 
    private void LoginWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        if (!locator.LoginVM.IsLogged) { Current.Shutdown(); }
    }
 
    private void LoginVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "IsLogged")
        {
            if (locator.LoginVM.IsLogged)
            {
                MainWindow.Show();
                loginWindow.Close();
            }
            else
            {
                Current.Shutdown();
            }
        }
    }
    static void MyHandler(object sender, UnhandledExceptionEventArgs args)
    {
        Exception e = (Exception)args.ExceptionObject;
        MessageBox.Show("MyHandler caught : " + e.Message);
        MessageBox.Show("Runtime terminating: {0}", args.IsTerminating.ToString());
    }
}


Добавлено через 2 часа 37 минут
Andrey-MSK, Элд Хасп, Я короче понял о чем вы, но не могу найти причину, уже все перенес в новый проект там оставил только логин и главное окно убрал все лишнее и все равно при закрытии окна логина приложение висит
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
06.02.2024, 17:41
firnen_dragon, А вы в App.xaml StartUpURI убрали?
XML
1
2
3
4
5
<Application x:Class="DBClient.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:DBClient"
             ShutdownMode="OnMainWindowClose">
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
06.02.2024, 17:43  [ТС]
Andrey-MSK, Ну да, там просто Startup:
XML
1
2
3
4
5
6
7
8
9
10
11
<Application x:Class="QrDesktop.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:QrDesktop"
             xmlns:locators="clr-namespace:QrDesktop.Locators"
             ShutdownMode="OnLastWindowClose"
             Startup="OnStartup">
    <Application.Resources>
        <locators:Locator x:Key="locator"/>
    </Application.Resources>
</Application>
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
06.02.2024, 19:45
Цитата Сообщение от firnen_dragon Посмотреть сообщение
И так:
ShutdownMode="OnExplicitShutdown":
- При закрытии окна логина на X: приложение закрывается
- При закрытии главного окна(больше не остается никаких окон) на X после авторизации: приложение не закрывается
При условии, что клик Х окна логина вызывает принудительной аборт приложения.

ShutdownMode="OnLastWindowClose":
- При закрытии окна логина на X: приложение закрывается
- При закрытии ПОСЛЕДНЕГО окна (больше не остается никаких окон) на X после авторизации: приложение закрывается
ShutdownMode="OnMainWindowClose":
- При закрытии окна логина на X: приложение закрывается
- При закрытии главного окна (НЕ ВАЖНО есть ещё окна или нет) на X после авторизации: приложение закрывается
А вам какое поведение нужно в вашем приложении?

Добавлено через 2 минуты
Цитата Сообщение от firnen_dragon Посмотреть сообщение
уже все перенес в новый проект там оставил только логин и главное окно убрал все лишнее и все равно при закрытии окна логина приложение висит
На Git загрузите и дайте ссылку.
Лучше всё не относящееся к вопросу удалить.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
07.02.2024, 14:49  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
А вам какое поведение нужно в вашем приложении?
Ну как я понимаю, если у меня стоит OnLastWindowClose, то я могу убрать код ниже и приложение все равно должно закрываться, если окно логина закрывается на X, но приложение остается висеть со всеми закрытыми окнами.
C#
1
2
3
4
5
6
loginWindow.Closing += LoginWindow_Closing;
 
private void LoginWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    if (!locator.LoginVM.IsLogged) { Current.Shutdown(); }
}
Написал минимальный пример, вот ссылка на гит, ветка main
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
07.02.2024, 14:58
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Написал минимальный пример, вот ссылка на гит
C#
1
2
3
4
5
6
7
8
9
10
11
protected void OnStartup(object sender, StartupEventArgs e)
{
    locator = (Locator)Resources["locator"];
    // Это можно убрать и создавать окно где надо перед его открытием
    MainWindow = mainWindow = new MainWindow();
    loginWindow = new LoginWindow();
    //loginWindow.Closing += LoginWindow_Closing;
    // отписываться от события кто будет?
    locator.LoginVM.PropertyChanged += LoginVM_PropertyChanged;
    loginWindow.Show();
}
1
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,772
07.02.2024, 15:00
Цитата Сообщение от firnen_dragon Посмотреть сообщение
но приложение остается висеть со всеми закрытыми окнами
Коллекцию 'System.Windows.Application.Current.Wind ows' проверьте на предмет всех закрытых окон.

И 'System.Windows.Application.Current.Main Window' тоже.

Вдруг что-то не совсем закрылось или какой-нибудь ваш самописный оконнный менеджер какие-то окна зажал и не отдаёт.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
07.02.2024, 15:08  [ТС]
Andrey-MSK, О, сработало, если запихать инициализацию главного окна в PropertyChange, то приложение наконец завершается на X
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void LoginVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if (e.PropertyName == "IsLogged")
    {
        if (locator.LoginVM.IsLogged)
        {
            MainWindow = mainWindow = new MainWindow();
            locator.LoginVM.PropertyChanged -= LoginVM_PropertyChanged;
            MainWindow.Show();
            loginWindow.Close();
        }
        else
        {
            Current.Shutdown();
        }
    }
}
Добавлено через 1 минуту
Чет я не подозревал, что это так работает оказывается

Добавлено через 40 секунд
Спасибо большое за помощь!
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.02.2024, 15:08
Помогаю со студенческими работами здесь

WPF MVVM + EFCore Передача данных между окнами
Всем привет! Столкнулся с проблемой при передачи/обновлении свойств между окнами. 1. Есть главное окно MainWindowViewModel.cs в...

Паттерн MVVM. Обмен данными между окнами с использованием ViewModels
Добрый день! Помогите, пожалуйста, понять тему насчет передачи данных в окошко с помощью ViewModel. Есть два окна MainView и LoginView,...

Управление окнами друг из друга
Есть программа при открытии которой, открывается окно авторизации. На окне авторизации можно зарегистрироваться или войти в программу с...

Управление окнами в многооконном приложении
Я сейчас делаю проект с очень большим количеством форм. И мне надо сделать чтобы формы открывались по тригерам. Я использую для...

Управление окнами Windows, а так же регуляция громкости в системе
Добрый день. Подскажите пожалуйста. Необходимо сделать следующее: Есть кнопки &quot;Открыть папку&quot;,&quot;Переключиться на следующее...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Транскрипция 55-минутного видео через Whisper: WhisperDesktop облажался, спас Google Colab[
anaschu 01.06.2026
Понадобилось получить текст из свежезагруженного видео на YouTube. Казалось бы, задача на пять минут. Заняла полтора часа. Делюсь опытом — может кому пригодится последовательность решений. . . .
21 мат мед. Планы на развитие модели здравоСохранения
anaschu 01.06.2026
AnyLogic: план развития симуляционной модели рабочего коллектива — динамический абсентеизм, реальные данные, три сценария сравнения Продолжаю серию постов о дискретно-событийной модели рабочего. . .
20. Мат мед. Абсентеизм как отдельный тип простоя
anaschu 29.05.2026
Апдейт модели: исправленные баги, абсентеизм и новые механизмы Продолжаю развивать ранее описанную модель рабочего коллектива на AnyLogic. За последние несколько дней был проведён серьёзный. . .
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
"Прокси" для последовательного порта
Eddy_Em 28.05.2026
Эту штуку написал я достаточно давно. Но сейчас вот понадобилось настроить датчик грозы, но при этом не отключать его от "метеодемона". Соответственно, надо запустить этот "прокси": метеодемон будет. . .
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru