I\'ve tried a huge amount of ways to get a static reference of my window across my program. I need to access all of its members at runtime from different classes, so a stati
Try this ((MainWindow)App.Current.Windows[0]).MainCanvas.
I have used this with success. Declare a static variable of the window type. Then in the constructor of the window set the static variable to "this". I have used it throughout the app and it seems to be working fine from within static or instance methods.
public static MainWindow screenMain = null;
public MainWindow()
{
InitializeComponent();
screenMain = this; //static reference to this.
}
For instance I am able to do this.
private delegate void del();
....
screenMain.Dispatcher.Invoke(new del(delegate()
{
screenMain.ButtonSubmit.IsEnabled = true;
screenMain.ButtonPreClearing.IsEnabled = true;
}));
It is absolutely possible to instantiate your own windows with WPF. But yes, you would have to be on the "UI thread" (which is a STA thread).
For example, say that we would like to have a property on our App class that exposes some window.
public partial class App
{
private static Window _myWindow;
public static Window1 MyWindow
{
get
{
if (_myWindow == null)
_myWindow = new Window1();
return _myWindow;
}
}
}
The problem with this code is, as you have experienced, depending on what thread is calling the MyWindow getter, new Window1()
will fail if the thread is not an STA.
To make sure the window is created on the right thread, enter the Dispatcher object. This object is used throughout WPF to make sure that communication between UI elements is done on the correct thread.
Back to our new Window1
, we can use the App.Dispatcher object to make sure the new
operation is done on the main application thread, like this:
public static Window1 MyWindow
{
get
{
if (_myWindow == null)
{
var window =
Application.Current.Dispatcher.Invoke(
new Func<Window1>(() => new Window1()));
_myWindow = (Window1)window;
}
return _myWindow;
}
}
Here, I get a hold on the current application's Dispatcher object and calls Invoke
with a delegate that does the actual newing. Invoke
ensures that my delegate is executed on the correct thread, and returns the result. Voila, the window is created without the dreaded STA error.
Now, what you must have in mind is that further calls made on the MyWindow instance must also be made on the correct thread. To avoid littering your code with calls to Dispatcher.Invoke, it could be useful to wrap the window instance behind a simple API. E.g. a Show method could be implemented like this, making sure to marshal the Show call via the Dispatcher object of the window:
public static void ShowMyWindow()
{
MyWindow.Dispatcher.Invoke(new Action(MyWindow.Show));
}
Create a static class that can contain the window object, and then when the window is created, have it pass itself to the static class, from then on the static class can hand out the window object to interested parties even though the window object itself is not static. Something like this. There is no need for your form to be static, you just need a static place to hold the form object.
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; } }
}