假设有一个控制台应用程序,它将文本打印到命令窗口。还有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元素?
答案 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
时,文本块都会自动更新