Перенесіть вікно на фронт у WPF


214

Як я можу перенести свою програму WPF на передню частину робочого столу? Поки я намагався:

SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true);

SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);

Жоден з яких не виконує цю роботу ( Marshal.GetLastWin32Error()говорить про те, що ці операції завершені успішно, а атрибути P / Invoke для кожного визначення є SetLastError=true).

Якщо я створюю новий пустий додаток WPF і дзвоню SwitchToThisWindowза допомогою таймера, він працює точно так, як очікувалося, тому я не впевнений, чому він не працює в моєму початковому випадку.

Редагувати : я роблю це разом із глобальною гарячою клавішею.


Ви перевірили, що MainWindow - це потрібне вікно? Від MSDN: MainWindow автоматично встановлюється з посиланням на перший об'єкт Window, який буде інстанціюватися в AppDomain.
Тодд Уайт

Гарна думка, але це єдине Вікно в додатку.
Фактор Містик

Чи можете ви дати трохи більше контекстного коду?
Тодд Уайт

Відповіді:


314
myWindow.Activate();

Спроби вивести вікно на перший план і активувати його.

Це повинно зробити трюк, якщо я неправильно зрозумів і ви не хочете, щоб Ви завжди були в топі. У такому випадку ви хочете:

myWindow.TopMost = true;

14
Я просто використовував myWindow.Show (), а іноді він не був зверху. Я зателефонував до свого вікна. Активуйте () відразу після цього, і він спрацював.
Бермо

4
Активувати іноді не працює в Windows XP. Я рекомендую відповідь @Matthew Xavier.
Lex Li

Трохи дивно, оскільки за замовчуванням ShowActivate увімкнено.
greenoldman

1
Перша відповідь хороша, за це дякую! Але другий рядок коду, використовуючи Topmostвластивість, є поганою практикою, оскільки може затьмарити інші спливаючі діалоги та несподівану поведінку.
Джонатан Перрі

2
Насправді це можна зробити за допомогою цього: if (myWindow.WindowState == WindowState.Minimized) myWindow.WindowState = WindowState.Normal;Як не дивно, він також збереже будь-які максимізовані вікна та не поверне їх до нормального стану.
r41n

168

Я знайшов рішення, яке підводить вікно до вершини, але воно поводиться як звичайне вікно:

if (!Window.IsVisible)
{
    Window.Show();
}

if (Window.WindowState == WindowState.Minimized)
{
    Window.WindowState = WindowState.Normal;
}

Window.Activate();
Window.Topmost = true;  // important
Window.Topmost = false; // important
Window.Focus();         // important

1
Чудовий натяк! TopMost робить чари в Windows 7, якщо вікно вже відкрите, але нижче інших вікон.
gsb

Це зробило трюк і для мене. Дякуємо gsb за додатковий коментар про те, як виглядає дивне використання TopMost!
Джен

1
Спасибі - виправлення було коротким і милим.
code4life

2
У моєму випадку Window.Activate () та Window.Focus () були достатніми. Налаштування Window.TopMost непотрібне.
вірний

6
Не використовуйте Window.Focus(). Це захопить фокус від того, що користувач наразі набирає у текстовому полі, що шалено засмучує кінцевих користувачів. Код, що знаходиться вище, працює чудово без нього.
Контанго

32

У випадку, якщо вам потрібно, щоб вікно було спереду при першому завантаженні, тоді слід скористатися наступним:

private void Window_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
}

private void Window_Initialized(object sender, EventArgs e)
{
    this.Topmost = true;
}

1
Якщо ви розробите щось подібне до Launchy ( launchy.net ) в C #, вам слід помітити, що ця відповідь майже марна.
Lex Li

21

Щоб зробити це швидким способом скопіювати -
скористайтеся DoOnProcessметодом цього класу для переміщення головного вікна процесу на передній план (але не для крадіжки фокусу з інших вікон)

public class MoveToForeground
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);

    const int SWP_NOMOVE        = 0x0002;
    const int SWP_NOSIZE        = 0x0001;            
    const int SWP_SHOWWINDOW    = 0x0040;
    const int SWP_NOACTIVATE    = 0x0010;
    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

    public static void DoOnProcess(string processName)
    {
        var allProcs = Process.GetProcessesByName(processName);
        if (allProcs.Length > 0)
        {
            Process proc = allProcs[0];
            int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
            // Change behavior by settings the wFlags params. See http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx
            SetWindowPos(new IntPtr(hWnd), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
        }
    }
}

HTH


6
+1 це єдина відповідь, яка була корисною для мене. У мене є додаток з одним майстром і кількома плаваючими рабами вікон. Після активації будь-якого з них всі інші вікна також повинні бути виведені спереду. Але не активується / набирає фокус, як підказує більшість відповідей: це катастрофа, оскільки це робить вікно, яке в даний момент натиснуто не натискає, оскільки раптом інше вікно набуває фокус.
stijn

Будь-яка причина не використовувати process.MainWindowHandle?
Шрірам Сактівель,

У моєму випадку я не хотів головного вікна, але погодився, є й інші способи отримати hWnd. FWIW HwndSourceоб'єкт працював добре.
tobriand

21

Я знаю, що це питання досить старе, але я просто натрапив на цей точний сценарій і хотів поділитися рішенням, яке я реалізував.

Як зазначалося в коментарях на цій сторінці, кілька запропонованих рішень не працюють на XP, що мені потрібно підтримати в моєму сценарії. Хоча я погоджуюся з думкою @Matthew Xavier, що в цілому це погана практика UX, є випадки, коли це цілком правдоподібна UX.

Рішення щодо приведення вікна WPF до вершини мені було надано тим самим кодом, який я використовую для надання глобальної гарячої клавіші. Стаття в блозі Джозефа Куні містить посилання на його зразки коду, що містить оригінальний код.

Я трохи очистив і змінив код і реалізував його як метод розширення до System.Windows.Window. Я перевірив це на XP 32 біт і Win7 64 біт, обидва вони працюють правильно.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace System.Windows
{
    public static class SystemWindows
    {
        #region Constants

        const UInt32 SWP_NOSIZE = 0x0001;
        const UInt32 SWP_NOMOVE = 0x0002;
        const UInt32 SWP_SHOWWINDOW = 0x0040;

        #endregion

        /// <summary>
        /// Activate a window from anywhere by attaching to the foreground window
        /// </summary>
        public static void GlobalActivate(this Window w)
        {
            //Get the process ID for this window's thread
            var interopHelper = new WindowInteropHelper(w);
            var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);

            //Get the process ID for the foreground window's thread
            var currentForegroundWindow = GetForegroundWindow();
            var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);

            //Attach this window's thread to the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);

            //Set the window position
            SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);

            //Detach this window's thread from the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);

            //Show and activate the window
            if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
            w.Show();
            w.Activate();
        }

        #region Imports

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        [DllImport("user32.dll")]
        private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        #endregion
    }
}

Я сподіваюся, що цей код допомагає іншим, хто стикається з цією проблемою.


Гей, шукай там! Я боровся з цим місяцями! Це працює для моїх ситуацій. Дивовижно! (Windows 7 x64)
mdiehl13

Насправді, здається, це працює, лише якщо я це роблю: App.mainWindow.Show (); SystemWindows.GlobalActivate (App.mainwindow); // Коли я видаляю перше .show (), він не виводить на фронт
mdiehl13

+1 для SetWindowPos (), я шукав спосіб лише привести своє вікно на фронт, не перебиваючи інших програм і не кравши фокус. this.Activate () вкрадає фокус.
prettyvoid

Це зробило це для мене, і в моєму випадку вся справа в тому, щоб вкрасти фокус, як це сталося, коли користувач взаємодіяв з певним елементом. так що спасибі багато це, здається, працює послідовно! просто this.Activate()здається, що виклик працює лише деякий час.
Пітер

13

Якщо користувач взаємодіє з іншою програмою, можливо, ви не зможете вивести своїх на перший план. Як правило, процес може розраховувати на встановлення вікна переднього плану, лише якщо цей процес уже є процесом переднього плану. (Майкрософт документує обмеження у записі MSDN SetForegroundWindow () . Це відбувається тому, що:

  1. Користувач "володіє" переднім планом. Наприклад, було б вкрай прикро, якби інша програма вкрала передній план, коли користувач набирає текст, принаймні перериває її робочий процес і, можливо, спричиняє ненавмисні наслідки, оскільки її натискання клавіш, призначене для однієї програми, порушник неправильно трактує, поки вона не помітить зміни .
  2. Уявіть, що кожна з двох програм перевіряє, чи є її вікно переднього плану, і намагається встановити його на передній план, якщо його немає. Як тільки запускається друга програма, комп'ютер стає непридатним, оскільки передній план відскакує між ними при кожному перемиканні завдань.

Гарна думка. Призначення коду полягало у поєднанні з глобальною гарячою клавішею, хоча й інші програми роблять це якось.
Фактор Містик

Доведеться використовувати PInvoke в C #, щоб імітувати те, що описано в цій статті, codeproject.com/Tips/76427/…
Lex Li

Тоді чому виразні поєднання помилок спливаючих вікон залишаються видимими, коли я часом переходжу на візуальну студію? : - /
Simon_Weaver

Саймоне, я підозрюю, що спливаючі помилки, які ви бачите, - це "найвищі" вікна (проектне рішення яких я не схвалюю). Існує різниця між вікном переднього плану (яке отримує введення користувача) та "найвищим" вікном у порядку Z. Будь-яке вікно може зробити себе "найвищим", яке розміщує його у всіх не найвищих вікнах, але не надає фокусу клавіатурі вікна і т. Д. Так, як стає вікно переднього плану.
Меттью Ксав'є

Трюк не вдається для кількох спеціальних вікон. У візуальній студії та вікнах командних рядків повинно бути щось, що не дозволяє іншим вікнам стати вікном переднього плану.
Лекс Лі

9

Я знаю, що це пізня відповідь, можливо, корисна для дослідників

 if (!WindowName.IsVisible)
 {
     WindowName.Show();
     WindowName.Activate();
 }

9

Чому деякі відповіді на цій сторінці помилкові!

  • Будь-яка відповідь, яка використовує, window.Focus()є неправильною.

    • Чому? Якщо з'явиться повідомлення-сповіщення, window.Focus()це захопить фокус від того, що користувач набирає під час. Це для шалених користувачів неприємно засмучує, особливо якщо спливаючі вікна трапляються досить часто.
  • Будь-яка відповідь, яка використовує, window.Activate()є неправильною.

    • Чому? Це також зробить видимі будь-які батьківські вікна.
  • Будь-яка відповідь, що пропускає, window.ShowActivated = falseє неправильною.
    • Чому? Це захопить фокус від іншого вікна, коли спливе повідомлення, що дуже дратує!
  • Будь-яка відповідь, яка не використовується Visibility.Visible для приховування / показу вікна, неправильна.
    • Чому? Якщо ми використовуємо Citrix, якщо вікно не буде згорнуте, коли воно закрите, воно залишить на екрані дивне чорне прямокутне утримання. Таким чином, ми не можемо використовувати window.Show()і window.Hide().

По суті:

  • При активації вікно не повинно захоплювати фокус від іншого вікна;
  • Вікно не повинно активувати його батьків, коли воно відображається;
  • Вікно має бути сумісним із Citrix.

Рішення MVVM

Цей код на 100% сумісний із Citrix (відсутні порожні області екрану). Він тестується як з нормальним WPF, так і з DevExpress.

Ця відповідь призначена для будь-якого випадку використання, коли нам потрібно невелике вікно сповіщень, яке завжди знаходиться навпроти інших вікон (якщо користувач вибере це у своїх налаштуваннях).

Якщо ця відповідь здається більш складною, ніж інші, це тому, що це надійний код на рівні підприємства. Деякі з інших відповідей на цій сторінці прості, але насправді не працюють.

XAML - приєднана власність

Додайте цю додану властивість до будь-якого UserControlвікна. Вкладене властивість:

  • Зачекайте, поки Loaded подія буде запущена (інакше вона не може шукати візуальне дерево, щоб знайти батьківське вікно).
  • Додайте обробник подій, який гарантує, що вікно видно чи ні.

У будь-який момент ви можете встановити вікно спереду чи ні, перевернувши значення доданого властивості.

<UserControl x:Class="..."
         ...
         attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
             "{Binding EnsureWindowInForeground, Mode=OneWay}">

C # - Хелперний метод

public static class HideAndShowWindowHelper
{
    /// <summary>
    ///     Intent: Ensure that small notification window is on top of other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoForeground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Visible)
            {
                window.Visibility = Visibility.Visible;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = true;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }

    /// <summary>
    ///     Intent: Ensure that small notification window can be hidden by other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoBackground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Collapsed)
            {
                window.Visibility = Visibility.Collapsed;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = false;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }
}

Використання

Щоб скористатися цим, вам потрібно створити вікно у вашому ViewModel:

private ToastView _toastViewWindow;
private void ShowWindow()
{
    if (_toastViewWindow == null)
    {
        _toastViewWindow = new ToastView();
        _dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
    }
    ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
    HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}

private void HideWindow()
{
    if (_toastViewWindow != null)
    {
        HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
    }
}

Додаткові посилання

Щоб отримати поради щодо того, як гарантувати, що вікно сповіщень завжди повертається назад на видимий екран, дивіться мою відповідь: У WPF, як перенести вікно на екран, якщо воно не ввімкнене з екрана? .


5
"Код рівня підприємства" та кілька рядків пізніше catch (Exception) { }. Так, правильно ... І він використовує код, який навіть не відображається у відповіді як _dialogServiceабо ShiftWindowOntoScreenHelper. Плюс із проханням створити вікно в стороні viewmodel (яка в основному порушує весь шаблон MVVM) ...
Kryptos,

@Kryptos Це код на рівні підприємства. Я набрав це з пам'яті, і ця точна методика використовується у великій компанії FTSE100. Справжнє життя дещо менш незаймане порівняно з ідеальними моделями дизайну, до яких ми всі прагнемо.
Контанго

Мені не подобається те, що ми зберігаємо екземпляр вікна у моделі перегляду, як Криптос згадував, що порушує всю точку mvvm, можливо, це могло бути зроблено замість коду?
Ігор

1
@Igor Meszaros Погодився. Тепер, коли я маю більше досвіду, якби мені довелося це зробити ще раз, я б додав поведінку та керував би нею, Func<>що пов'язане з ViewModel.
Контанго

7

У мене була подібна проблема із програмою WPF, яка викликає програму Access через об’єкт Shell.

Моє рішення нижче - працює в XP та Win7 x64 з додатком, складеним на ціль x86.

Я б набагато скоріше зробив це, ніж імітувати вкладку alt.

void Window_Loaded(object sender, RoutedEventArgs e)
{
    // make sure the window is normal or maximised
    // this was the core of the problem for me;
    // even though the default was "Normal", starting it via shell minimised it
    this.WindowState = WindowState.Normal;

    // only required for some scenarios
    this.Activate();
}

4

Ну, оскільки це така гаряча тема ... ось що для мене працює. У мене виникли помилки, якщо я цього не зробив, тому що Activate () помилиться на вас, якщо ви не побачите вікно.

Xaml:

<Window .... 
        Topmost="True" 
        .... 
        ContentRendered="mainWindow_ContentRendered"> .... </Window>

Код позаду:

private void mainWindow_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
    this.Activate();
    _UsernameTextBox.Focus();
}

Це був єдиний спосіб для мене, щоб вікно було показане зверху. Потім активуйте його, щоб ви могли вводити поле, не встановлюючи фокус за допомогою миші. control.Focus () не буде працювати, якщо вікно Active ();


2

Добре я розібрався в роботі. Я телефоную з гачка клавіатури, який використовується для впровадження швидкої клавіші. Виклик працює так, як очікувалося, якщо я вставлю його в BackgroundWorker з паузою. Це хитрість, але я поняття не маю, чому він не працював спочатку.

void hotkey_execute()
{
    IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
    BackgroundWorker bg = new BackgroundWorker();
    bg.DoWork += new DoWorkEventHandler(delegate
        {
            Thread.Sleep(10);
            SwitchToThisWindow(handle, true);
        });
    bg.RunWorkerAsync();
}

Мене просто цікавить: Ви спробували Window.Activate (як запропонував Morten) та інші пропозиції? Вони здаються менш вибагливими, ніж ця визнана хижість.
Саймон Д.

Це було досить давно, але так, у той час, коли я це намагався
Factor Mystic

Це не працює на моєму Windows XP. Я рекомендую відповідь @Matthew Xavier.
Lex Li

2

Щоб показати будь-яке відкрите вікно, імпортуйте ці DLL:

public partial class Form1 : Form
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);
    [DllImportAttribute("User32.dll")]
    private static extern int SetForegroundWindow(int hWnd);

і в програмі Ми шукаємо додаток із вказаним заголовком (написати назву без першої літери (індекс> 0))

  foreach (Process proc in Process.GetProcesses())
                {
                    tx = proc.MainWindowTitle.ToString();
                    if (tx.IndexOf("Title of Your app WITHOUT FIRST LETTER") > 0)
                    {
                        tx = proc.MainWindowTitle;
                        hWnd = proc.Handle.ToInt32(); break;
                    }
                }
                hWnd = FindWindow(null, tx);
                if (hWnd > 0)
                {
                    SetForegroundWindow(hWnd);
                }

"Назва вашого додатка БЕЗ ПЕРШОГО ЛИСТА" Ой, хакі-хакі-хакі. Чому б IndexOfзамість цього не використовувати належним чином?
Гонки легкості на орбіті

1

Проблема може полягати в тому, що потік, що викликає ваш код з гачка, не був ініціалізований під час виконання, тому виклики методів виконання не працюють.

Можливо, ви могли б спробувати зробити Invoke для маршалу свого коду на потік інтерфейсу, щоб викликати ваш код, який виводить вікно на передній план.


1

Ці коди справно працюватимуть.

Спочатку встановіть активований обробник подій у XAML:

Activated="Window_Activated"

Додайте нижче рядок до свого блоку конструктора Main Window:

public MainWindow()
{
    InitializeComponent();
    this.LocationChanged += (sender, e) => this.Window_Activated(sender, e);
}

А всередині активованого обробника подій скопіюйте ці коди:

private void Window_Activated(object sender, EventArgs e)
{
    if (Application.Current.Windows.Count > 1)
    {
        foreach (Window win in Application.Current.Windows)
            try
            {
                if (!win.Equals(this))
                {
                    if (!win.IsVisible)
                    {
                        win.ShowDialog();
                    }

                    if (win.WindowState == WindowState.Minimized)
                    {
                        win.WindowState = WindowState.Normal;
                    }

                    win.Activate();
                    win.Topmost = true;
                    win.Topmost = false;
                    win.Focus();
                }
            }
            catch { }
    }
    else
        this.Focus();
}

Ці кроки будуть добре працювати і перенесуть усі інші вікна у вікно батьків.


0

Якщо ви намагаєтесь приховати вікно, наприклад, ви мінімізуєте вікно, я виявив, що використовую

    this.Hide();

приховає це правильно, а потім просто використовуючи

    this.Show();

буде показано вікно як найпопулярніший елемент ще раз.


0

Просто хотів додати ще одне рішення цього питання. Ця реалізація працює для мого сценарію, де CaliBurn відповідає за показ головного вікна.

protected override void OnStartup(object sender, StartupEventArgs e)
{
    DisplayRootViewFor<IMainWindowViewModel>();

    Application.MainWindow.Topmost = true;
    Application.MainWindow.Activate();
    Application.MainWindow.Activated += OnMainWindowActivated;
}

private static void OnMainWindowActivated(object sender, EventArgs e)
{
    var window = sender as Window;
    if (window != null)
    {
        window.Activated -= OnMainWindowActivated;
        window.Topmost = false;
        window.Focus();
    }
}

0

Не забувайте не ставити код, який показує це вікно всередині обробника PreviewMouseDoubleClick, оскільки активне вікно повернеться до вікна, яке обробляло подію. Просто помістіть його в обробник подій MouseDoubleClick або зупиніть бульбашку, встановивши e.Handled на True.

У моєму випадку я обробляв PreviewMouseDoubleClick на Listview і не встановлював e.Handled = true, тоді він піднімав фокус події MouseDoubleClick назад до початкового вікна.


-1

Я створив метод розширення, щоб зробити його легким заново.

using System.Windows.Forms;
    namespace YourNamespace{
        public static class WindowsFormExtensions {
            public static void PutOnTop(this Form form) {
                form.Show();
                form.Activate();
            }// END PutOnTop()       
        }// END class
    }// END namespace

Зателефонуйте в конструктор форми

namespace YourNamespace{
       public partial class FormName : Form {
       public FormName(){
            this.PutOnTop();
            InitalizeComponents();
        }// END Constructor
    } // END Form            
}// END namespace

Привіт Майку. Ви відповідаєте на це питання досить пізно. Чи можете ви пояснити у своїй відповіді, чому цей підхід відрізняється (а може, і краще) від дуже хороших відповідей, які вже були розміщені на це питання?
Ноель Відмер

Тільки пізно, як мені просто потрібно було це зробити, і я натрапив на це і хотів поділитися тим, як я вирішив проблему, якщо інші хочуть її використовувати.
Майк

Звичайно, мене обрали для перегляду вашої публікації і хотіли вас повідомити. Завжди добре надати нову відповідь, якщо ви думаєте, що це хороший внесок у громаду.
Ноель Відмер

2
Це питання стосувалося конкретно WPF, але ваше рішення стосується WinForms.
Брайан Райхле
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.