2009-01-26 113 views
11

我最近开始了一个C#项目(VS 2008)作为一个'控制台'项目,我写了一些库,测试程序等。现在我想添加几个WPF窗口,但它看起来像控制台项目获胜别让我这样做。我来自Java,所以这有点奇怪。我如何添加一个WPF表单(我将从我的“主”类实例化我的自我?)控制台项目中的WPF窗口?

回答

0

您确定需要控制台项目吗?您可以创建'WPF应用程序'项目并向库中添加引用等。如果尝试从控制台应用程序中显示WPF窗口,则会因为线程模型在控制台&之间的差异而产生异常WPF应用程序

+4

[STAThread]为主要方法,属性,使得它可能! – 2010-06-15 10:17:14

3

您应该将库代码移动到其他“类库”项目并使用它从控制台项目,你的WPF窗口应该在另一个“WPF应用程序”项目中,该项目也将引用你的“类库”

0

感谢aku和Dmitriy,我创建了另一个项目PF),它将引用我的基于控制台的代码。

37

接受的答案并非完全正确,恐怕只需在mainmethod之前添加[STAThread]属性并引用正确的库(如System.Windows),并且您都将设置为添加wpf窗口。

编辑:在评论@JamesWilkins给我提供了这个有用的链接:http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

+0

你是对的彼得! – 2010-06-15 10:17:56

+0

接受的答案在理论上是正确的。他所问的只是他是否确实需要控制台应用程序。但我必须同意,我更喜欢你的答案,作为解决这个确切问题的答案。 – 2013-12-15 09:30:52

14

我有同样的问题,并寻找一个类似的答案。我找到了各地的信息,所以我把我在一个地方找到的信息。我还需要一种方法来隐藏和显示控制台窗口,所以我发现了这个工作(对于VS 2013+):

  1. 创建一个新的控制台项目(一定要选择你需要的.NET framework版本使用 - 我需要自己使用.Net 4.0)。确保有以下引用:

    • PresentationFramework
    • PresentationCore
    • WindowsBase
    • System.xaml
  2. 在Solution Explorer中的项目上单击右键,选择 “属性“,并将项目输出类型更改为Windows应用程序。 这可以防止控制台窗口在启动时显示(如果您要 需要,请跳过此步骤)。

  3. 虽然控制控制台窗口对于添加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,所以在这里我们(在这种情况下,零)测试,如果手柄为null,如果是这样,则需要创建一个控制台窗口(仅一次)。在此之后,GetConsoleWindow();将始终返回要使用的句柄。

  4. 正如另一个答案已经说过,你需要对控制台的Main方法实施前的行添加[STAThread]。这是必需的,因为WPF需要在Single Threaded Apartment环境中运行。

    [STAThread] 
        static void Main(string[] args) 
        { 
        } 
    
  5. 添加窗口:要做到这一点,只需添加一个用户控件到项目,并命名为“主窗口”(或任何你喜欢)。只需右键单击解决方案资源管理器中的项目节点,然后选择Add->User Control...。打开后面的MainWindow.xaml.cs代码并将MainWindow : UserControl更改为MainWindow : Window。接下来,打开MainWindow.xaml文件,并将第一个标记<UserControl更改为<Window(并确保结束标记也被重命名,如果使用Visual Studio,则该标记应该是自动的)。关闭所有“MainWindow”编辑器选项卡并重新打开(只是为了确保,可能不需要)。您应该看到MainWindow.xaml现在在设计窗格中显示一个窗口。

  6. 显示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();但是,这意味着您必须在创建对象的同一线程中创建UI对象(除其他外)。为了与新线程通信,我只使用Dispatcher类(WinApp.Dispatcher.BeginInvoke())在WPF中运行请求线程上下文。

对于Windows 10/10:如果您在调试和你没有看到在输出窗口中的任何文字,到这里看看:https://stackoverflow.com/a/49145317/1236397