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