如何从控制台应用程序访问UI元素

时间:2016-07-05 12:17:08

标签: c# wpf multithreading

假设有一个控制台应用程序,它将文本打印到命令窗口。还有Logger WPF窗口,它必须复制输出。 IDE强制我在新线程(STA)中创建窗口:

public SomeClass()
{
    var loggerThread = new Thread(() =>
    {
        var logWindow = new Window
        {
            Title = "Logger", Width = 100, Height = 100
        };

        var stackPanel = new StackPanel 
        {
            Name = "stackPanel"
        };

        stackPanel.Children.Add(new TextBlock 
        {
            Name = "textBlock", Text = "new text\n"
        });

        logWindow.Content = stackPanel;
        logWindow.ShowDialog();
    });

    loggerThread.SetApartmentState(ApartmentState.STA);
    loggerThread.IsBackground = true;
    loggerThread.Start();
}

public void PutInfo(string msg)
{
    // how to access textBlock here?
    ...textBlock.Text = "some info";
}

如何在线程启动后访问textBlock.Text。 换句话说,如何通过PutInfo()方法从其他类访问该线程中的UI元素?

1 个答案:

答案 0 :(得分:2)

你在这里划了几行, 控制台应用程序是一个没有图形元素的应用程序

WPF应用程序是一个具有图形用户界面的应用程序,WPF定义了界面。

所以通过定义控制台应用程序不能有GUI

现在,如果您尝试在GUI中记录控制台应用程序的输出,那么您可以使用System.Diagnostics中的Process Class来捕获和显示控制台输出通道,这里很好地解释了Capturing console output from a .NET application (C#)

如果您希望控制台应用程序直接控制不同的GUI应用程序控件,那么您正在破坏内存管理,应该考虑使用非托管内存指针,但我不建议这样做

如果您只是尝试更新WPF文本块,那么这很简单,只需将文本存储在可观察集合或实现INotifyPropertyChanged的字符串属性中,然后使用绑定进行更新,就可以将您的记录器类设置为可观察的

public class Logger:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged
    private string _Description;
    public static readonly PropertyChangedEventArgs DescriptionProperty = new PropertyChangedEventArgs(nameof(Description));

    public string Description
    {
        get { return _Description; }
        set
        {
            _Description = value;
            PropertyChanged?.Involke(this, DescriptionProperty);
        }
    }
}

然后这就是更新控件所需的全部内容

<TextBox Text="{Binding Description, source="Your Logger"}"/>

然后,每次使用setter更改Description时,文本块都会自动更新