如何获得WPF窗口的静态引用?

我已经尝试了很多方法来获取我的程序中窗口的静态引用。 我需要在运行时从不同的类访问其所有成员,因此需要静态引用。

我想要的是Program.Window1 ,其中Core是静态的, MyWindow是其静态成员之一。

在WinForms中,我通常在Program.cs中声明我的静态表单,但这似乎不适用于WPF及其自定义的“App.xaml”ApplicationDefinition。

我该怎么做?

注意:我已经尝试了很多方法:使用直接调用新窗口(即Program.Window1 = new Window1() )将不起作用,因为我得到一些线程无效exception。 据我所知,到目前为止,只有ApplicationDefinitions可以在WPF中启动窗口。

每当我尝试按“代码”而不是默认的XAML ApplicationDefinition的StartupUri创建一个窗口时,这是个例外:

调用线程必须是STA,因为许多UI组件都需要这个。

创建一个可以包含窗口对象的静态类,然后在创建窗口时,让它将自身传递给静态类,从那时起,静态类可以将窗口对象分发给感兴趣的各方,即使窗口对象本身是不是静止的。 像这样的东西。 您的表单不需要是静态的,只需要一个静态的位置来保存表单对象。

 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; } } } 

试试这个((MainWindow)App.Current.Windows [0])。MainCanvas。

使用WPF实例化自己的窗口绝对是可能的。 但是,是的,你必须在“UI线程”(这是一个STA线程)。

例如,假设我们希望在App类上有一个公开某个窗口的属性。

  public partial class App { private static Window _myWindow; public static Window1 MyWindow { get { if (_myWindow == null) _myWindow = new Window1(); return _myWindow; } } } 

正如您所经历的那样,此代码的问题是,根据调用MyWindow getter的线程,如果线程不是STA,则new Window1()将失败。

要确保在右侧线程上创建窗口,请输入Dispatcher对象 。 在整个WPF中使用此对象以确保UI元素之间的通信在正确的线程上完成。

回到我们new Window1 ,我们可以使用App.Dispatcher对象来确保在主应用程序线程上完成new操作,如下所示:

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

在这里,我获取当前应用程序的Dispatcher对象,并使用执行实际新建的委托调用InvokeInvoke确保我的委托在正确的线程上执行,并返回结果。 瞧,窗口是在没有可怕的STA错误的情况下创建的。

现在,您必须要记住的是,必须在正确的线程上对MyWindow实例进行进一步调用。 为了避免在调用Dispatcher.Invoke时乱丢代码,将窗口实例包装在一个简单的API后面会很有用。 例如,Show方法可以像这样实现,确保通过窗口的Dispatcher对象封送Show调用:

  public static void ShowMyWindow() { MyWindow.Dispatcher.Invoke(new Action(MyWindow.Show)); } 

我成功地使用了它。 声明窗口类型的静态变量。 然后在窗口的构造函数中将静态变量设置为“this”。 我在整个应用程序中使用它,它似乎在静态或实例方法中工作正常。

  public static MainWindow screenMain = null; public MainWindow() { InitializeComponent(); screenMain = this; //static reference to this. } 

例如,我能够做到这一点。

  private delegate void del(); .... screenMain.Dispatcher.Invoke(new del(delegate() { screenMain.ButtonSubmit.IsEnabled = true; screenMain.ButtonPreClearing.IsEnabled = true; }));