[ACCEPTED]-WPF window from a Console project?-console

Accepted answer
Score: 40

The accepted answer is not entirely true, I'm 6 afraid, just add the [STAThread] attribute 5 before your mainmethod and make references 4 to the right libraries (like System.Windows) and 3 you're all set to add wpf windows.

EDIT 2 : in the comments @JamesWilkins supplied 1 me with this usefull link : http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

Score: 33

I had the same question and was looking 63 for a similar answer. I found info all 62 over the place, so I'm putting what I found 61 in one place. I also needed a way to hide 60 and show the console window, so I found 59 out this worked (for VS 2013+):

  1. Create a 58 new console project (be sure to select the 57 .NET framework version you need to use - I 56 needed to use .Net 4.0 myself). Make sure 55 to have the following references:

    • PresentationFramework
    • PresentationCore
    • WindowsBase
    • System.xaml
  2. Right-click 54 on the project in the solution explorer, select "Properties", and 53 change the project Output Type to Windows 52 Application. This prevents the console 51 window from showing on startup (if you want 50 that, skip this step).

  3. While controlling 49 the console window is not necessary in order 48 to add WPF windows, it can be useful. If 47 you don't need this, skip to #4. In the 46 "Program" class for the console, add 45 this in order to control the window:

    public class Program
    {
      [DllImport("kernel32.dll", SetLastError = true)]
      static extern bool AllocConsole(); // Create console window
    
      [DllImport("kernel32.dll")]
      static extern IntPtr GetConsoleWindow(); // Get console window handle
    
      [DllImport("user32.dll")]
      static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    
      const int SW_HIDE = 0;
      const int SW_SHOW = 5;
    

    This 44 allows to create, hide, and show the console 43 window. I created these methods to do this:

      static void ShowConsole()
      {
          var handle = GetConsoleWindow();
          if (handle == IntPtr.Zero)
              AllocConsole();
          else
              ShowWindow(handle, SW_SHOW);
      }
    
      static void HideConsole()
      {
          var handle = GetConsoleWindow();
          if (handle != null)
              ShowWindow(handle, SW_HIDE);
      }
    

    These 42 are mostly self explanatory, but if the 41 project is in window mode, GetConsoleWindow(); returns null, so 40 here we test if the handle is null (zero 39 in this case), and if so, a console window 38 needs to be created (only once). After 37 this, GetConsoleWindow(); will always return a handle to use.

  4. As 36 stated in another answer already, you need to 35 add [STAThread] on a line before your console's Main method. This 34 is required, as WPF needs to run in a Single Threaded Apartment environment.

      [STAThread]
      static void Main(string[] args)
      {
      }
    
  5. Adding a window: To 33 do this, just add a user control to your 32 project and name it "MainWindow" (or 31 whatever you like). Just right-click the 30 project node in the solution explorer and 29 select Add->User Control.... Open the MainWindow.xaml.cs code 28 behind and change MainWindow : UserControl to MainWindow : Window. Next, open the 27 MainWindow.xaml file and change the first 26 tag <UserControl to <Window (and make sure the closing tag 25 gets renamed also, which should be automatic 24 if using Visual Studio). Close all "MainWindow" editor 23 tabs and reopen (just to be sure, may not 22 be necessary). You should see MainWindow.xaml 21 now show a window in the design pane.

  6. Showing the WPF window: To 20 do this, we need to start the window message 19 loop, which is really easy. To begin, I 18 created some properties to store the objects. Just 17 put this somewhere in the Program class.

    public static Application WinApp { get; private set; }
    public static Window MainWindow { get; private set; }
    

    Next we 16 have to create the message loop by creating 15 a System.Windows.Application object, then pass it the main window. I 14 created this method to perform this task:

    static void InitializeWindows()
    {
        WinApp = new Application();
        WinApp.Run(MainWindow = new MainWindow()); // note: blocking call
    }
    

    and 13 that's it! To test this, put some content 12 in your main window and do this:

    [STAThread]
    static void Main(string[] args)
    {
        ShowConsole(); // Show the console window (for Win App projects)
        Console.WriteLine("Opening window...");
        InitializeWindows(); // opens the WPF window and waits here
        Console.WriteLine("Exiting main...");
    }
    

Hope that 11 helps saves someone time, cheers! ;)

TIP: I 10 found it helpful, in my case, to call InitializeWindows() in 9 a new thread; however, that means that you 8 must create UI objects (among other things) in 7 the the same thread that the Application object was 6 created in. To communicate with the new 5 thread, I just used the Dispatcher class (WinApp.Dispatcher.BeginInvoke()) to run 4 requests in the WPF thread context.

For Windows 3 8/10: If you are debugging and you don't 2 see any text in your output window, take 1 a look here: https://stackoverflow.com/a/49145317/1236397

Score: 2

You should move your library code to some 4 other "Class library" project and use it 3 from your Console project. Your WPF windows 2 should be in another "WPF application" project 1 which will also reference your "Class library".

Score: 0

Thanks to aku and Dmitriy, I create another 2 project (WPF) which will reference my console 1 based code.

More Related questions