为什么在添加新文本时,行之间有空行?
Why when adding new text the lines have empty lines between them?
private void Println(string text, SolidColorBrush brush) => Dispatcher.Invoke(() =>
{
RichTextBoxLogger.Document.Blocks.Add(new Paragraph(new Run(text) { Foreground = brush }));
});
private void Println(string text)
{
Println(text, Brushes.LawnGreen);
}
private void PrintMsg(string message)
{
Println($"[+] {message}", Brushes.Yellow);
}
private void PrintErr(Exception e)
{
Println($"[-] {e}", Brushes.Red);
}
正在使用
private void Fsw_Deleted(object sender, FileSystemEventArgs e)
{
string time = DateTime.Now.ToString("h:mm:ss tt");
string output = $"[*] {e.Name}: \"Deleted At : {time}\"";
Println(output);
}
结果是:
我想添加这几行,它们之间没有空行。
为了防止两个连续段落之间出现中断,您必须将 Paragraph.KeepWithNext
属性 设置为 true
:
var paragraphWithoutBreak = new Paragraph { KeepWithNext = true };
我不建议您使用繁重的 RichTextBox
来完成您的任务。当输出增长时它会变慢。而是使用灯 ListBox
。 ListBox
具有 UI 虚拟化功能,将显着提高性能。当您将 ListBoxItem.IsHitTestVisible
设置为 false
时,ListBox
看起来和感觉起来就像一个 read-only 文档。为每个消息类型定义一个 DataTemplate 以控制输出的外观:
ILogMessage.cs
interface ILogMessage
{
string Message { get; }
}
ErrorMessage.cs
一条红色消息。
class ErrorMessage : ILogMessage
{
// TODO::Implement interface and add a constructor that accepts a message.
}
WarningMessage.cs
一条黄色消息。
class WarningMessage : ILogMessage
{
// TODO::Implement interface and add a constructor that accepts a message.
}
InfoMessage.cs
一条绿色消息。
class InfoMessage : ILogMessage
{
// TODO::Implement interface and add a constructor that accepts a message.
}
MainWindow.xaml.cs
partial class MainWindow : Window
{
public ObservableCollection<ILogMessage> Messages { get; }
public MainWindow()
{
InitializeConmponent();
this.Messages = new ObservableCollection<ILogMessage>();
}
private void WriteInfoLine(string message)
=> this.Messages.Add(new InfoMessage(message));
private void WriteWarningLine(string message)
=> this.Messages.Add(new WarningMessage(message));
private void WriteErrorLine(string message)
=> this.Messages.Add(new ErrorMessage(message));
}
MainWindow.xaml
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:InfoMessage}">
<TextBlock Text="{Binding Message, Mode=OneTime}"
Foreground="LawnGreen" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:WarningMessage}">
<TextBlock Text="{Binding Message, Mode=OneTime}"
Foreground="Yellow" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ErrorMessage}">
<TextBlock Text="{Binding Message, Mode=OneTime}"
Foreground="Red" />
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Messages}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible"
Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Window>
请参阅 了解如何在添加新项目时将消息视图滚动到底部。您可以使用示例的 LogMessageBox
控件(一个 UserControl
)并替换上面的 ListBox
.
private void Println(string text, SolidColorBrush brush) => Dispatcher.Invoke(() =>
{
RichTextBoxLogger.Document.Blocks.Add(new Paragraph(new Run(text) { Foreground = brush }));
});
private void Println(string text)
{
Println(text, Brushes.LawnGreen);
}
private void PrintMsg(string message)
{
Println($"[+] {message}", Brushes.Yellow);
}
private void PrintErr(Exception e)
{
Println($"[-] {e}", Brushes.Red);
}
正在使用
private void Fsw_Deleted(object sender, FileSystemEventArgs e)
{
string time = DateTime.Now.ToString("h:mm:ss tt");
string output = $"[*] {e.Name}: \"Deleted At : {time}\"";
Println(output);
}
结果是:
我想添加这几行,它们之间没有空行。
为了防止两个连续段落之间出现中断,您必须将 Paragraph.KeepWithNext
属性 设置为 true
:
var paragraphWithoutBreak = new Paragraph { KeepWithNext = true };
我不建议您使用繁重的 RichTextBox
来完成您的任务。当输出增长时它会变慢。而是使用灯 ListBox
。 ListBox
具有 UI 虚拟化功能,将显着提高性能。当您将 ListBoxItem.IsHitTestVisible
设置为 false
时,ListBox
看起来和感觉起来就像一个 read-only 文档。为每个消息类型定义一个 DataTemplate 以控制输出的外观:
ILogMessage.cs
interface ILogMessage
{
string Message { get; }
}
ErrorMessage.cs
一条红色消息。
class ErrorMessage : ILogMessage
{
// TODO::Implement interface and add a constructor that accepts a message.
}
WarningMessage.cs
一条黄色消息。
class WarningMessage : ILogMessage
{
// TODO::Implement interface and add a constructor that accepts a message.
}
InfoMessage.cs
一条绿色消息。
class InfoMessage : ILogMessage
{
// TODO::Implement interface and add a constructor that accepts a message.
}
MainWindow.xaml.cs
partial class MainWindow : Window
{
public ObservableCollection<ILogMessage> Messages { get; }
public MainWindow()
{
InitializeConmponent();
this.Messages = new ObservableCollection<ILogMessage>();
}
private void WriteInfoLine(string message)
=> this.Messages.Add(new InfoMessage(message));
private void WriteWarningLine(string message)
=> this.Messages.Add(new WarningMessage(message));
private void WriteErrorLine(string message)
=> this.Messages.Add(new ErrorMessage(message));
}
MainWindow.xaml
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:InfoMessage}">
<TextBlock Text="{Binding Message, Mode=OneTime}"
Foreground="LawnGreen" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:WarningMessage}">
<TextBlock Text="{Binding Message, Mode=OneTime}"
Foreground="Yellow" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ErrorMessage}">
<TextBlock Text="{Binding Message, Mode=OneTime}"
Foreground="Red" />
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Messages}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible"
Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Window>
请参阅 LogMessageBox
控件(一个 UserControl
)并替换上面的 ListBox
.