所以我目前正在尝试打印从进程到richtextbox的消息,除了我希望它以红色文本显示错误消息和绿色的正常消息之外,一切都很好。
由于某些原因,它全部是绿色的,我认为这是因为我绑定了前景而不是附加到RTB但是我不确定。
如何正确地将错误消息变为红色并且正常消息变为绿色。
MainWindow.cs
public partial class MainWindow : Window
{
static Server server = new Server();
private readonly Thread ConsoleThread = new Thread(() => { server.Start("Start.bat"); });
public MainWindow()
{
InitializeComponent();
DataContext = server;
}
private void ButtonStart(object sender, RoutedEventArgs e)
{
ConsoleThread.Start();
}
private void tbConsole_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
=> tbConsole.ScrollToEnd();
}
Server.cs
class Server : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Process pServer = new Process();
private Brush color;
public Brush MessageColor
{
get { return color; }
set
{
color = value;
OnPropertyChanged("MessageColor");
}
}
private string outStream;
public string OutputStream
{
get { return outStream; }
set
{
if (!string.IsNullOrEmpty(value))
{
outStream += value + Environment.NewLine;
OnPropertyChanged("OutputStream");
}
}
}
public void Start(string Path)
{
pServer.StartInfo.FileName = Path;
pServer.StartInfo.UseShellExecute = false;
pServer.StartInfo.RedirectStandardOutput = true;
pServer.StartInfo.RedirectStandardError = true;
pServer.OutputDataReceived += OKDataReceived;
pServer.ErrorDataReceived += ErrorDataReceived;
pServer.Start();
pServer.BeginOutputReadLine();
pServer.BeginErrorReadLine();
}
private void OKDataReceived(object sender, DataReceivedEventArgs e)
{
MessageColor = Brushes.Green;
OutputStream = e.Data;
}
private void ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
MessageColor = Brushes.Red;
OutputStream = e.Data;
}
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handle = PropertyChanged;
if (handle != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
XAML
<Grid>
<Button Click="ButtonStart" Content="Start" Margin="325,63,353,319"/>
<xctk:RichTextBox FontSize="5" Name="tbConsole" Margin="143,149,164,81" BorderBrush="Gray" Padding="10" ScrollViewer.VerticalScrollBarVisibility="Auto" Text="{Binding Path=OutputStream, Mode=TwoWay}" Foreground="{Binding Path=MessageColor}" />
</Grid>
答案 0 :(得分:1)
是的,我认为你是对的:Foreground
属性是指RichTextBox
中的所有文字,而不是单个项目。
我可以建议解决你的问题,但请耐心等待......
分别收集邮件
当我说“消息”时,我的意思是将任何内容传递给OKDataReceived
和ErrorDataReceived
。
您的架构中存在一个问题,即您无法区分“好”消息和“坏”消息。 OutputStream
包含两者,当MessageColor
更改时,它将针对之前的所有消息进行更改,而不仅仅是最新消息。
我建议更改创建一个带有消息文本的Message
类,以及一个标记,指出它是“好”消息还是“坏消息”。当您从流程中获取新数据时,您可以创建Message
并相应地设置“好”或“坏”的标记。
然后将OutputStream
替换为ObservableCollection<Message>
类型的属性。从流程中创建新的Message
后,您可以将其添加到此ObservableCollection<Message>
。这是最终将绑定到您的视图的属性。请注意,当新项目添加到ObservableCollection
时,它会自动刷新绑定。
现在,我没有忘记关于如何在视图上以不同颜色显示文本的原始问题。我可以给你一个建议,但这取决于模型中有ObservableCollection<Message>
。
将邮件转换为FlowDocument
将ObservableCollection<Message>
绑定到RichTextBox
控件,但使用IValueConverter
将所有Messages
转换为FlowDocument
。每条消息都将转换为Paragraph
,其中Run
将包含文本。然后,您可以将段落上的Foreground
属性设置为Message
中标志的正确颜色。您还需要将该属性绑定到RichTextBox.Document
属性。 RichTextBox
的MSDN文章有一个很好的例子,我认为你可以从中找到答案。
这种方法的主要缺点是,只要流程发出新消息,就需要将整个ObservableCollection
再次转换为FlowDocument
,而不仅仅是新项目。但我认为这对性能的影响微乎其微。
我认为这是最好的方法。最后,您将拥有一个带有可区分消息的视图模型,一个可以根据需要进行修改的转换器,以及对视图本身的一些更改。