I want to change the formatting in a richtextbox in two ways:
Example for my second requierement: My richtextbox got the text
stackoverflow
and the caret cursor is between stackover and flow like this:
stackover|flow
Now I need to change the fontsize on the current caret position for example to 20. On further writing I just want the text on this position displayed bigger. I don't want to change the current existing text. Like:
stackovercoolflow
cool should be in fontsize 20 now and stackover flow in default font size (like before)
I found a lot of answers but nothing of them helped me.
Most hints were:
But nothing of them worked for me...
Mostly I oriented myself on the following question wpf-richtextbox-fontface-fontsize
Currently I ended up with the followed code, but it only changes text-selection.
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel Orientation="Vertical">
<RichTextBox Height="300" Width="300" x:Name="MyRichTextBox" />
<ComboBox Width="300" x:Name="cmbbx" SelectedIndex="1" SelectionChanged="ComboBox_SelectionChanged" />
</StackPanel>
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace WpfApp2
{
public partial class MainWindow : Window
{
public ObservableCollection<double> Werte { get; set; }
public MainWindow()
{
Werte = new ObservableCollection<double>();
Werte.Add(4);
Werte.Add(10);
Werte.Add(20);
Werte.Add(55);
InitializeComponent();
cmbbx.ItemsSource = Werte;
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var newSize = (double)cmbbx.SelectedValue;
TextRange r = new TextRange(MyRichTextBox.Selection.Start, MyRichTextBox.Selection.End);
r.ApplyPropertyValue(TextElement.FontSizeProperty, newSize);
}
}
}
This just changes text-selection. There is no formatting when nothing is selected (just cursor is set). I am working with .net 5
Probably you want something like below:
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="60" x:Name="cmbbx" SelectedIndex="1" SelectionChanged="ComboBox_SelectionChanged" HorizontalAlignment="Left"/>
<RichTextBox Grid.Row="1" x:Name="rtb" AllowDrop="True" VerticalScrollBarVisibility="Auto" Padding="2"
SelectionChanged="rtb_SelectionChanged"
TextChanged="rtb_TextChanged">
<FlowDocument/>
</RichTextBox>
</Grid>
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Collections.ObjectModel;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
var Werte = new ObservableCollection<double> { 4, 10, 16, 20, 26, 55 };
InitializeComponent();
cmbbx.ItemsSource = Werte;
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!rtb.Selection.IsEmpty)
{
if (cmbbx.SelectedValue is double newSize)
{
var range = new TextRange(rtb.Selection.Start, rtb.Selection.End);
range.ApplyPropertyValue(TextElement.FontSizeProperty, newSize);
}
}
}
// Use `TextChanged` event to apply the currently selected font size to the entered text
private void rtb_TextChanged(object sender, TextChangedEventArgs e)
{
// Disable recursive calling this event handler
rtb.TextChanged -= rtb_TextChanged;
foreach (var change in e.Changes)
{
if (cmbbx != null)
{
TextPointer tp = rtb.Document.ContentStart.GetPositionAtOffset(change.Offset);
var range = new TextRange(tp, tp.GetPositionAtOffset(1, LogicalDirection.Backward));
if (!string.IsNullOrEmpty(range.Text) && cmbbx.SelectedValue is double fontsize)
{
range.ApplyPropertyValue(TextElement.FontSizeProperty, fontsize);
}
}
}
// Restore the event handler
rtb.TextChanged += rtb_TextChanged;
}
// The following `SelectionChanged` event handler is used to set a font size in the combobox
// depend on the current caret location.
private void rtb_SelectionChanged(object sender, RoutedEventArgs e)
{
if (rtb.Selection is TextSelection selection)
{
if (selection.GetPropertyValue(TextElement.FontSizeProperty) is double fsize)
{
foreach (var it in cmbbx.Items)
{
if ((double)it == fsize)
{
// The currently selected document fragment is containing font with size presented in the ComboBox
cmbbx.SelectedItem = it;
return;
}
}
}
// The currently selected document fragment contains fonts
// with different font sizes or the font size doesn't included to the the combobox
cmbbx.SelectedItem = null;
}
}
}
}
I added some notes in the code above. Let me know if an additional descriptions are required.