【问题标题】:Emulating a console with a WPF window使用 WPF 窗口模拟控制台
【发布时间】:2013-01-18 23:18:52
【问题描述】:

首先,免责声明,您将要见证的是我近 20 年来的第一次编码。我是 C# 和 WPF 的新手,尝试了解 WPF 不仅仅是一项挑战。

在过去的一个月里,我一直在开发一个宠物项目控制台应用程序,它一直表现良好。我现在正试图通过向项目添加现代 GUI 来更进一步。

我想通过使用包裹在 WPF 窗口中的滚动条内的 WPF 文本块来模拟控制台(只是基本的输出功能)。您可以see the original console application in action here 更好地了解我要模拟的控制台输出类型。但是我在基本函数调用方面遇到了一个大问题,我认为这是因为我不完全了解 WPF/C# 的工作原理。

应用程序通过 Main() 在代码中启动,如下所示:

 class Program
{
    public static ConsoleWindow MainConsole = new ConsoleWindow();

    [STAThread]
    static void Main(string[] args)
    {
        Application MyApplication = new Application();
        MyApplication.Run(MainConsole);

        // The following code does not work, it produces no output in the Textblock
        MainConsole.WriteLine("Crystal Console");
        MainConsole.WriteLine("Version: " + Properties.Settings.Default.BuildVersion);
        MainConsole.WriteLine("Current Time: " + DateTime.Now);
        MainConsole.WriteLine("Last Login: " + Properties.Settings.Default.dateLastLogin);
    }
}

问题是调用的方法似乎对文本块的内容没有任何影响。

虽然我将提供大量信息以备不时之需,但问题本身很简单:为什么从同一窗口上的文本框控件获取内容时,Textblock 更新正常,但没有'在 Main() 中调用相同方法时不显示任何更新?

出于测试目的,该窗口有几个文本框,它们在窗口内调用 .WriteLine 方法,并且可以正常工作,所以我知道 .WriteLine 代码没有问题,您可以在此处查看:

public void WriteLine(string Message = null, string Sender = null)
    {
        _Console.AddElement(new ConsoleElement(Sender, Message + "\n"));
        _Console.DisplayContent(ConsoleTextBlock);
        ConsoleScroller.ScrollToEnd();
    }

这是控制台本身的代码,以备不时之需,“ConsoleElement”类本质上只是一个对象,其中包含要在文本块中显示的消息以及每个消息的格式。

class ConsoleStream
{
    IList<ConsoleElement> ConsoleElements = new List<ConsoleElement>();

    public void AddElement(ConsoleElement NewElement)
    {
        if (NewElement.Sender == null)  // Sender is System not user.
        {
            NewElement.Content = "     " + NewElement.Content;
            NewElement.Font = new FontFamily("Arial");
            NewElement.FontSize = 12;
        }
        ConsoleElements.Add(NewElement);
    }

    public void ClearElements()
    {
        ConsoleElements.Clear();
    }

    public void DisplayContent(TextBlock sender)
    {
        sender.Text = null;
        foreach (ConsoleElement Message in ConsoleElements)
        {
            //If message is a status update, i.e. has no sender, format it as a system message.
            if (Message.Sender != null)
            {
                sender.Inlines.Add(new Run(Message.Sender + ": ") { Foreground = Message.SenderColour, FontFamily = Message.Font, FontSize = Message.FontSize });
            }
            //if message has a sender it's either the user or the AI. Format it as a user message.
            if (Message.Sender != null) sender.Inlines.Add(new Run(Message.Content) { Foreground = Message.ContentColour, FontFamily = Message.Font, FontSize = Message.FontSize });
            else sender.Inlines.Add(new Run(Message.Content) { Foreground = Message.SystemColour, FontFamily = Message.Font, FontSize = Message.FontSize });
        }
    }
}

【问题讨论】:

    标签: c# wpf console


    【解决方案1】:

    MyApplication.Run(MainConsole);控制线程,它之后的代码在你关闭窗口之后才会执行。

    将代码移至 ConsoleWindow 的加载(或初始化)方法

    【讨论】:

    • 这解释了很多。谢谢你的回答。我将移动代码,看看是否效果更好。从表面上看,我将不得不习惯运行附加到窗口对象的代码。
    • 出于好奇,有没有办法将代码保留在原处,并且不会让窗口劫持线程?
    • 不使用 .Run 方法。您可以使用 .StartUp、msdn.microsoft.com/en-us/library/… 进行检查,但您仍然需要移动一些代码。
    猜你喜欢
    • 2011-03-18
    • 2010-10-03
    • 1970-01-01
    • 2013-02-03
    • 2022-01-14
    • 2017-09-09
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    相关资源
    最近更新 更多