Окно 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), который будет ссылаться на мой консольный код.