Как получить статическую ссылку на Окно WPF?

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

То, что я хотел бы иметь, является чем-то как Program.Window1, где Core статично и MyWindow один из его статических участников.

В WinForms я обычно объявляю свою статическую форму в Program.cs, но это, кажется, не работает с WPF и их пользовательским "App.xaml" ApplicationDefinition.

Как я могу сделать это?

Примечание: Я уже попробовал много путей: использование прямого вызова нового окна (т.е. Program.Window1 = new Window1()) не будет работать, поскольку я получаю некоторое недействительное исключение потока. Как я понимаю до сих пор, только ApplicationDefinitions может запустить окна в WPF.

Вот исключение каждый раз, когда я пытаюсь создать окно "кодом" а не ApplicationDefinition XAML по умолчанию StartupUri:

Вызывающим потоком должен быть STA, потому что много компонентов UI требуют этого.

8
задан Lazlo 13 February 2010 в 21:49
поделиться

2 ответа

Потому что вы сказали:

сделал на последних спринтах, может быть .

Я склонен согласиться с нечетким леденцом (и + 1 от меня).

Однако, если есть что-то, что вы знаете придется сделать, но это было размещено к самому концу, это просто в неправильном месте, если это может иметь серьезные архитектурные последствия.

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

-121--1665225-

Деление на ноль допустимо для чисел с плавающей точки.

  • 1/0 дает Бесконечность.
  • (-1 )/0 дает -Infinity.
  • 0/0 дает NaN.

Эти «числа» правильно определены в IEEE 754.

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

-121--2623152-

Создайте статический класс, который может содержать оконный объект, а затем, когда окно будет создано, передать себя статическому классу, с этого момента статический класс может передать оконный объект заинтересованным вечеринкам, даже если сам оконный объект не является статическим. Что-то вроде этого. Нет необходимости в том, чтобы форма была статичной, нужно просто статическое место для хранения объекта формы.

public class Core
{
     internal static MyWindowClass m_Wnd = null;

     // call this when your non-static form is created
     //
     public static void SetWnd(MyWindowClass wnd)
     {
         m_Wnd = wnd;
     }

     public static MyWindow { get { return m_Wnd; } }
}
11
ответ дан 5 December 2019 в 07:35
поделиться

Создание собственных окон с помощью WPF абсолютно возможно. Но да, вы должны быть в «потоке пользовательского интерфейса» (который является потоком STA).

Например, предположим, что мы хотели бы иметь свойство в нашем классе App, которое предоставляет какое-то окно.

    public partial class App
    {
        private static Window _myWindow;

        public static Window1 MyWindow
        {
            get
            {
                if (_myWindow == null)
                    _myWindow = new Window1();
                return _myWindow;
            }
       }
    }

Проблема с этим кодом, как вы испытали, в зависимости от того, какой поток вызывает метод получения MyWindow, new Window1 () завершится ошибкой, если поток не является STA.

Чтобы убедиться, что окно создается в правильном потоке, введите объект Dispatcher . Этот объект используется во всем WPF, чтобы обеспечить связь между элементами пользовательского интерфейса в правильном потоке.

Вернемся к нашему новому Window1 , мы можем использовать приложение.Объект Dispatcher, чтобы убедиться, что операция new выполняется в основном потоке приложения, например:

        public static Window1 MyWindow
        {
            get
            {
                if (_myWindow == null)
                {
                     var window = 
                             Application.Current.Dispatcher.Invoke(
                               new Func<Window1>(() => new Window1()));

                    _myWindow = (Window1)window;
                }

                return _myWindow;
            }
       }

Здесь я задерживаю объект Dispatcher текущего приложения и вызываю Invoke с делегат, который фактически обновляет. Invoke гарантирует, что мой делегат выполняется в правильном потоке, и возвращает результат. Вуаля, окно создается без ужасной ошибки STA.

Теперь вы должны иметь в виду, что дальнейшие вызовы экземпляра MyWindow также должны выполняться в правильном потоке. Чтобы избежать засорения вашего кода вызовами Dispatcher.Invoke, было бы полезно заключить экземпляр окна в простой API. Например. Метод Show может быть реализован следующим образом, при этом обязательно маршалируйте вызов Show через объект Dispatcher окна:

        public static void ShowMyWindow()
        {
            MyWindow.Dispatcher.Invoke(new Action(MyWindow.Show));
        }
4
ответ дан 5 December 2019 в 07:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: