Today I have a quickie that I thought would be worth sharing. Note that, even though I only present C# code in this article, the sample solution (see the bottom for the download) again contains both a project for C# and VB.
The problem
In the past 6 months, I've spent quite a while or two in the WPF forums, crawling over other peoples' questions and learning by answering them. A very common approach to answering is to simply post a sample window that i.e. demonstrates the solution to the OP's question. In the very beginning, I tended to have a sample app with a Window1 which got loaded upon startup, replacing the XAML and/or code-behind everytime I created a sample window. That meant that, everytime I tried something new, the earlier version was either lost or had to be copied into another window. Alternatively, I sometimes named windows and then changed App.xaml to show the window I wanted.
Any of the aforementioned approaches includes either a) the loss of previous work, or b) additional work everytime you add something or need to show a different (older) window. I hence thought it should be fairly easy to simply make a main window, provide a list of windows found throughout the application and just open them on a click (or double-click).
Reflection to the rescue
I must say I just love Reflection - it provides a convenient (well, most of all times) approach to obtain information that just wasn't possible (or only with many hacks) in pre-.Net-times!
Here goes.
Getting a list of all windows
Here's all you need to do in order to get all windows that are part of the executing assemlby (aka the exe):
public static IEnumerable<string> WindowNames
{
get
{
IEnumerable<string> ieWindowNames = null;
Assembly asm = Assembly.GetExecutingAssembly();
ieWindowNames =
from types in asm.GetTypes()
where types.BaseType.Name == "Window"
orderby types.Name
select types.Name;
return ieWindowNames;
}
}
The above returns a list (IEnumerable) that would allow for binding and, thanks to Linq, sorted alphabetically.
Displaying windows using their name
How about providing a convenient way of displaying a window when all you have is its name (i.e., taken from the previously introduced list)?
Again, this can be done with just a few lines:
public static bool? ShowWindowByName(string strWindowName, bool fShowDialog)
{
if (string.IsNullOrEmpty(strWindowName)) return null;
Assembly asm = Assembly.GetExecutingAssembly();
string strFullyQualifiedName = asm.GetName().Name + "." + strWindowName;
object obj = asm.CreateInstance(strFullyQualifiedName);
Window win = obj as Window;
if (win == null) return null;
if (fShowDialog)
{
win.ShowDialog();
return win.DialogResult;
}
else
{
win.Show();
return null;
}
}
The above method also allows you to show the window modally in which case the method will return the DialogResult after the window was closed.
WindowByName
The ShowWindowByName() method might actually do more than desired. If you only need a reference to a window by its name, here's another little helper method:
public static Window WindowByName(string strWindowName)
{
if (string.IsNullOrEmpty(strWindowName)) return null;
Assembly asm = Assembly.GetExecutingAssembly();
string strFullyQualifiedName = asm.GetName().Name + "." + strWindowName;
object obj = asm.CreateInstance(strFullyQualifiedName);
if (obj != null)
return obj as Window;
else
return null;
}
Closing all windows
If you're using VB, one way to close all open windows when your application exits is to specify this in the project's settings:

However, C# doesn't have a respective counterpart. And, anyway, I tend to rather have my own method for dealing with this, so here's another simple helper:
public static void CloseAllWindows()
{
Application app = Application.Current;
for (int intCounter = app.Windows.Count - 1; intCounter >= 0; intCounter--)
app.Windows[intCounter].Close();
}
Due to the simplicity, it's not really all too worth sharing (must say, I feeling a bit ashamed to post something like this), but I thought the method simply belongs to the class.
The sample solution
I've placed all of the above (basic documentation included - skipped in the article) into a simple class that you'll find in the solution (see the bottom for the download link). However, since I don't want to provide a bunch of windows just to allow to test things out, the projects' sample window only contains - besides the main window - a dummy second window to have at least two of them. Here's a screenshot:

The code-behind for the above is pretty short:
using System.Windows;
using System.Collections.Generic;
using System.Windows.Controls;
namespace CS
{
public partial class Main : Window
{
public Main()
{
InitializeComponent();
this.DataContext = this;
this.Unloaded += new RoutedEventHandler(MainWindow_Unloaded);
}
//Allows to bind the ListBox to the window names in this assembly
public IEnumerable<string> WindowNames { get { return Utils.WindowHelpers.WindowNames; } }
//Show a window after an item in the ListBox has been double-clicked.
private void lbWindows_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (lbWindows.SelectedItem != null)
{
Utils.WindowHelpers.ShowWindowByName(
lbWindows.SelectedItem.ToString(),
(bool)chkShowDialog.IsChecked
);
e.Handled = true;
}
}
void MainWindow_Unloaded(object sender, RoutedEventArgs e)
{
Utils.WindowHelpers.CloseAllWindows();
}
}
}
But wait!
In the code above, you may (or may not) have noted that the selected window is shown when double-clicking a window rather than after a single click has been performed. I have no idea as to why there isn't any DoubleClick-event for the ListBox control, but luckily, it's not all too hard to provide a dummy one. I can't take credit for that as this is something I stumbled over in this StackOverflow thread, so thanks go out to Bob King. All you'll have to remember when going that way though is to set e.Handled = true to avoid the message from bubbling up.
The last word
I presently don't really see much "real world" usage scenarios for the class, but my forums-life has gotten a hell of a lot easier. Using the class, I can simply add windows to my test-solution as they come and then access/run them by selecting them from a list of my pre-defined main window. One problem that this might impose on you (it does on me) - the time it takes to build your solution will increase rapidly. My present solution has short of 100 windows ...
The sample solution
I’ve created a sample solution that contains everything discussed here.
Download: WindowByName.zip (27.38 kb)
Location: SinglePost