#c_sharp #wpf #winforms
У меня есть окно, которое выполняет какой-то процесс с визуализацией. И мне надо чтобы при запуске приложение оно работало, но не показывалось (то есть чтобы произошло событие Load). При этом у пользователя всегда есть возможность его показывать и скрывать. Проблема в том что у меня не получается решить этот вопрос без начального мерцания из-за подобного кода. SomeWindow.Show(); SomeWindow.Hide(); Ни в Windows Forms, ни в WPF не вижу решения этой проблемы. Проблема также в том, что окно показывается в TaskBar, но только когда оно видимое. Поэтому мне не подходят хаки вроде Установки прозрачности окна. Установки нулевой широты, высоты и удаления рамок. Вынос окна за пределы экрана и т.д. Для чего это надо и почему нельзя всё вынести в какой-нибудь Task? Потому что код выполняемый окном зависит от визуализации. Мне нужно чтобы человек мог скрывать и показывать окно когда и сколько угодно, но чтобы его состояние было таким же как будто его не скрывали.
Ответы
Ответ 1
Просто так вам не получится вызвать событие Loaded: оно вызывается лишь тогда, когда ваше окно реально было показано. Но, возможно, у вас сработает обходной путь, который сработал в моём проекте. Для начала, мы отделим контент окна в UserControl. Окно пусть будет пустым. Контрол назовём SimpleUserControl для примера. Теперь мы в начале работы приложения создаём контрол, но не показываем его, таким образом: public partial class App : Application { protected override async void OnStartup(StartupEventArgs e) { base.OnStartup(e); var uc = new SimpleUserControl(); // создали контрол // возможно, надо установить DataContext var size = new Size(100, 100); // фейковый размер uc.Measure(size); // заставляем пробежать layout engine uc.Arrange(new Rect(size)); uc.UpdateLayout(); // дождёмся выполнения пустой лямбды на фоновом приоритете, // это даст время привязкам разрешиться await Dispatcher.CurrentDispatcher.InvokeAsync( () => { }, DispatcherPriority.Background); // теперь можно работать с контролом. я просто сделаю паузу для примера await Task.Delay(9000); // и вставить его в окно: new MainWindow() { Content = uc }.Show(); } } При этом Loaded на контроле всё ещё не вызывается (оно вызовется только при показе), но у вас подконтролы будут находиться в «рабочем» состоянии.Ответ 2
Получил ответ на англ. SO. Этот же код работает для WPF если заменить FormWindowState на WindowState. Суть в том, что надо сначала чтобы перед "показом" установить (в коде или дизайнере): SomeWindow.ShowInTaskbar = false; SomeWindow.WindowState = FormWindowState.Minimized; Затем выполнить код SomeWindow.Show(); SomeWindow.Hide(); И сразу после этого подготавливаем окно для нормального отображения при последующих вызовах SomeWindow.Show: SomeWindow.ShowInTaskbar = true; // Если надо чтобы форма показывалась на панели быстого запуска. SomeWindow.WindowState = FormWindowState.Normal; // или FormWindowState.Maximized если надо Это можно превратить в метод расширения для Windows Forms: public static class FormHelper { public static void ShowInvisible(this Form form) { // сохраняем параметры окна bool needToShowInTaskbar = form.ShowInTaskbar; FormWindowState initialWindowState = form.WindowState; // делаем окно невидимым form.ShowInTaskbar = false; form.WindowState = FormWindowState.Minimized; // показываем и скрываем окно form.Show(); form.Hide(); // восстанавливаем параметры окна form.ShowInTaskbar = needToShowInTaskbar; form.WindowState = initialWindowState; } } или для WPF: public static class WindowHelper { public static void ShowInvisible(this Window window) { // сохраняем параметры окна bool needToShowInTaskbar = window.ShowInTaskbar; WindowState initialWindowState = window.WindowState; // делаем окно невидимым window.ShowInTaskbar = false; window.WindowState = WindowState.Minimized; // показываем и скрываем окно window.Show(); window.Hide(); // восстанавливаем параметры окна window.ShowInTaskbar = needToShowInTaskbar; window.WindowState = initialWindowState; } }Ответ 3
Как я понял, при создании формы: её не должно быть видно, должно сработать событие Load, её иконка должна появиться на таскбаре, форма не не должна мелькнуть. По-моему, установка прозрачности в ноль перед показом, а после показа в единицу полностью решает проблему. var form = new Form(); form.Opacity = 0; form.Load += Form_Load; form.Show(); form.WindowState = FormWindowState.Minimized; form.Opacity = 1; Событие вызывается, форма не мелькает, на таскбаре отображается.
Комментариев нет:
Отправить комментарий