Окно WPF из проекта консоли?

Недавно я начал проект С# (VS 2008) в качестве проекта "Консоль", где я написал несколько библиотек, тестовых программ и т.д. Теперь я хотел бы добавить несколько окон WPF, но это похоже на консольный проект не позволит мне это сделать. Я прихожу с Java, так что это немного странно. Как я могу добавить WPF-форму (которую я создам самостоятельно из своего "основного" класса?

Ответ 1

Вы уверены, что вам нужен консольный проект? Вы можете создать проект "WPF application" и добавить ссылки на ваши библиотеки и т.д. Если попытаться показать окно WPF из консольного приложения, вы получите исключение из-за различий в модели потоков на консоль и приложениях WPF.

Ответ 2

Принятый ответ не совсем верен, я боюсь, просто добавьте атрибут [STAThread] перед вашим основным способом и сделайте ссылки на правильные библиотеки (например, System.Windows), и вы все настроены на добавление wpf-окон.

EDIT: в комментариях @JamesWilkins предоставил мне эту полезную ссылку: http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

Ответ 3

У меня был тот же вопрос и я искал аналогичный ответ. Я нашел информацию повсюду, поэтому я помещаю то, что нашел в одном месте. Мне также нужен способ скрыть и показать окно консоли, поэтому я выяснил, что это сработало (для VS 2013 +):

  • Создайте новый проект консоли (обязательно выберите версию .NET Framework, которую вам нужно использовать - мне нужно было использовать .Net 4.0). Убедитесь, что у вас есть следующие ссылки:

    • PresentationFramework
    • PresentationCore
    • WindowsBase
    • System.xaml
  • Щелкните правой кнопкой мыши проект в проводнике решений, выберите    "Свойства" и измените тип вывода проекта на приложение Windows.   Это предотвращает показ окна консоли при запуске (если вы   хотите, пропустите этот шаг).

  • Во время управления консольным окном необязательно добавлять окна WPF, это может быть полезно. Если вам это не нужно, перейдите к №4. В классе "Программа" для консоли добавьте это, чтобы управлять окном:

    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;
    

    Это позволяет создавать, скрывать и показывать окно консоли. Я создал эти методы для этого:

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

    Это, в основном, самоочевидные, но если проект находится в режиме окна, GetConsoleWindow(); возвращает null, поэтому здесь мы проверяем, является ли дескриптор нулевым (в данном случае равен нулю), и если это так, нужно окно консоли (только один раз). После этого GetConsoleWindow(); всегда будет возвращать дескриптор, который будет использоваться.

  • Как уже было сказано в другом ответе, вам нужно добавить [STAThread] в строку перед вашим консольным методом Main. Это необходимо, так как WPF необходимо запустить в среде Single Threaded Apartment.

      [STAThread]
      static void Main(string[] args)
      {
      }
    
  • Добавление окна:. Для этого просто добавьте пользовательский элемент управления в свой проект и назовите его "MainWindow" (или как вам нравится). Щелкните правой кнопкой мыши проект node в проводнике решений и выберите Add->User Control.... Откройте код MainWindow.xaml.cs и измените MainWindow : UserControl на MainWindow : Window. Затем откройте файл MainWindow.xaml и измените первый тег <UserControl на <Window (и убедитесь, что закрывающий тег также переименован, что должно быть автоматическим при использовании Visual Studio). Закройте все вкладки редактора "MainWindow" и снова откройте (просто убедитесь, что это не обязательно). Вы должны увидеть, что MainWindow.xaml теперь показывает окно в области проектирования.

  • Отображение окна WPF: Для этого нам нужно запустить цикл оконных сообщений, что очень просто. Для начала я создал некоторые свойства для хранения объектов. Просто поместите это где-нибудь в класс Program.

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

    Затем мы должны создать цикл сообщений, создав объект System.Windows.Application, а затем передадим ему главное окно. Я создал этот метод для выполнения этой задачи:

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

    и что это! Чтобы проверить это, поместите некоторый контент в основное окно и сделайте следующее:

    [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...");
    }
    

Надеюсь, что это поможет сэкономить время, ура!;)

СОВЕТ. Мне было полезно в моем случае вызвать InitializeWindows() в новом потоке; однако это означает, что вы должны создавать объекты пользовательского интерфейса (между прочим) в том же потоке, в котором был создан объект Application. Чтобы связаться с новым потоком, я просто использовал класс Dispatcher (WinApp.Dispatcher.BeginInvoke()) для запуска запросов в контексте потока WPF.

Ответ 4

Вы должны перенести свой библиотечный код в другой проект "Библиотека классов" и использовать его в своем проекте консоли. Ваши окна WPF должны быть в другом проекте "WPF application", который также будет ссылаться на вашу "библиотеку классов".

Ответ 5

Благодаря aku и Dmitriy, я создаю еще один проект (WPF), который будет ссылаться на мой консольный код.