Home > Net >  Why when adding new text the lines have empty lines between them?
Why when adding new text the lines have empty lines between them?

Time:05-09

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);
        }

Using it

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);
        }

The result is :

lines added with empty lines between them

I want to add this lines without empty lines between them.

CodePudding user response:

To prevent a break from occurring between two consecutive paragraphs, you must set the Paragraph.KeepWithNext property to true:

var paragraphWithoutBreak = new Paragraph { KeepWithNext = true };

I don't recommend to use the heavy RichTextBox for your task. It will become slow when the output grows. Instead use a light ListBox. ListBox features UI virtualization and will significantly improve the performance. When you set ListBoxItem.IsHitTestVisible to false, the ListBox will look and feel like a read-only document. Define a DataTemplate for each message type to control the appearance of the output:

ILogMessage.cs

interface ILogMessage
{
  string Message { get; }
}

ErrorMessage.cs
A red message.

class ErrorMessage : ILogMessage
{
  // TODO::Implement interface and add a constructor that accepts a message.
}

WarningMessage.cs
A yellow message.

class WarningMessage : ILogMessage
{
  // TODO::Implement interface and add a constructor that accepts a message.
}

InfoMessage.cs
A green message.

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>

See this example to know how to scroll the message view to the bottom when adding new items. You can use the example's LogMessageBox control (a UserControl) and replace the above ListBox.

  • Related