c# - 从 CaretPosition 在 RichTextBox 中写入样式文本
问题描述
我有一个RichTextBox
带有一些用于文本样式的标准按钮的 WPF。因为它们都应该以相同的方式工作,所以从现在开始,我将使用使文本变为粗体的示例。所以,我的目标是,用户可以单击粗体按钮,然后,他写的文本将从插入符号所在的位置变为粗体。必须在流文档的内联中设置样式(因为我必须将包括样式在内的整个文本作为 xaml 字符串传输到另一个对象)。在这一点上,我将发布我的代码。请注意,这是我创建的一个简单的测试项目,用于测试解决这个特定问题的方法。
首先是xaml:
<Window x:Class="rtbTest.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"
xmlns:local="clr-namespace:rtbTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="180"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<DockPanel
Grid.Row="0"
LastChildFill="False">
<StackPanel
DockPanel.Dock="Left"
Orientation="Horizontal"
Background="Gray">
<TextBlock
Foreground="#000000"
FontWeight="Bold"
VerticalAlignment="Center"
Text="Font"
/>
<ComboBox
x:Name="fonts"
Margin="10,2,20,2"
>
</ComboBox>
<TextBlock
Foreground="#000000"
FontWeight="Bold"
VerticalAlignment="Center"
Text="Size"
/>
<ComboBox
x:Name="fontsize"
Margin="10,2,20,2"
>
</ComboBox>
<ToggleButton
x:Name="bold"
Content="B"
Margin="0,2,5,2"
Width="30">
</ToggleButton>
<ToggleButton
x:Name="italic"
Content="I"
Margin="0,2,5,2"
Width="30">
</ToggleButton>
</StackPanel>
</DockPanel>
<RichTextBox
Name="textbox"
Grid.Row="1" Grid.ColumnSpan="2" >
</RichTextBox>
<ScrollViewer
Grid.Row="2"
Grid.ColumnSpan="2"
Margin="0,10,0,0"
VerticalScrollBarVisibility="Auto">
<StackPanel
Name="entrys"
Background="Black"
>
</StackPanel>
</ScrollViewer>
</Grid>
</Window>
然后是代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using function = System.String;
namespace rtbTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.InitializeTextStyling();
}
private void InitializeTextStyling()
{
this.AddFonts();
this.fonts.SelectedIndex = 1;
this.textbox.IsInactiveSelectionHighlightEnabled = true;
this.fonts.SelectionChanged += (s, a) =>
{
if (this.fonts.SelectedIndex != 0)
{
if (this.textbox.Selection.IsEmpty)
{
this.textbox.Document.FontFamily = ((ComboBoxItem)this.fonts.SelectedItem).Content as FontFamily;
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontFamilyProperty, ((ComboBoxItem)this.fonts.SelectedItem).Content as FontFamily);
}
}
};
for (double i = 10; i < 80; i = i + 1)
{
this.fontsize.Items.Add(i);
}
this.fontsize.SelectionChanged += (s, a) =>
{
if (this.textbox.Selection.IsEmpty)
{
this.textbox.Document.FontSize = double.Parse(this.fontsize.SelectedItem.ToString());
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontSizeProperty, double.Parse(this.fontsize.SelectedItem.ToString()));
}
};
this.fontsize.SelectedItem = 40.0;
this.italic.Checked += (s, a) =>
{
if (this.textbox.Selection.IsEmpty)
{
this.textbox.Document.FontStyle = FontStyles.Italic;
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontStyleProperty, FontStyles.Italic);
}
};
this.italic.Unchecked += (s, a) =>
{
if (this.textbox.Selection.IsEmpty)
{
this.textbox.Document.FontStyle = FontStyles.Normal;
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontStyleProperty, FontStyles.Normal);
}
};
this.bold.Checked += (s, a) =>
{
this.textbox.Focus();
if (this.textbox.Selection.IsEmpty)
{
TextPointer tp = this.textbox.CaretPosition;
Run r = new Run("test", tp);
r.FontWeight = FontWeights.Bold;
this.textbox.CaretPosition = r.ElementStart;
r.Text = "";
string fds = XamlWriter.Save(this.textbox.Document);
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontWeightProperty, FontWeights.Heavy);
}
};
this.bold.Unchecked += (s, a) =>
{
if (this.textbox.Selection.IsEmpty)
{
this.textbox.Document.FontWeight = FontWeights.Normal;
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontWeightProperty, FontWeights.Normal);
}
};
FlowDocument fd = new FlowDocument();
fd.FontSize = double.Parse(this.fontsize.SelectedItem.ToString());
fd.FontFamily = ((ComboBoxItem)this.fonts.SelectedItem).Content as FontFamily;
fd.FontWeight = FontWeights.Normal;
this.textbox.Document = fd;
}
private function GetStringFromStream(Stream stream)
{
using (StreamReader r = new StreamReader(stream))
{
return r.ReadToEnd();
}
}
private void AddFonts()
{
//foreach (System.Drawing.FontFamily f in System.Drawing.FontFamily.Families)
//{
// ComboBoxItem item = new ComboBoxItem();
// item.Content = new FontFamily(f.GetName(0));
// item.FontFamily = (FontFamily)item.Content;
// this.fonts.Items.Add(item);
//}
ComboBoxItem item = new ComboBoxItem();
item.Content = new FontFamily("Arial");
item.FontFamily = (FontFamily)item.Content;
this.fonts.Items.Add(item);
item = new ComboBoxItem();
item.Content = new FontFamily("Corbel");
item.FontFamily = (FontFamily)item.Content;
this.fonts.Items.Add(item);
item = new ComboBoxItem();
item.Content = new FontFamily("Gabriola");
item.FontFamily = (FontFamily)item.Content;
this.fonts.Items.Add(item);
item = new ComboBoxItem();
item.Content = new FontFamily("MingLiU - ExtB");
item.FontFamily = (FontFamily)item.Content;
this.fonts.Items.Add(item);
item = new ComboBoxItem();
item.Content = new FontFamily("MV Boli");
item.FontFamily = (FontFamily)item.Content;
this.fonts.Items.Add(item);
item = new ComboBoxItem();
item.Content = new FontFamily("Noto Naskh Arabic UI");
item.FontFamily = (FontFamily)item.Content;
this.fonts.Items.Add(item);
}
}
}
这段代码应该足以立即进行测试。
现在,我的问题出在这部分:
this.bold.Checked += (s, a) =>
{
this.textbox.Focus();
if (this.textbox.Selection.IsEmpty)
{
TextPointer tp = this.textbox.CaretPosition;
Run r = new Run("test", tp);
r.FontWeight = FontWeights.Bold;
this.textbox.CaretPosition = r.ElementStart;
r.Text = "";
string fds = XamlWriter.Save(this.textbox.Document);
}
else
{
this.textbox.Selection.ApplyPropertyValue(TextBlock.FontWeightProperty, FontWeights.Heavy);
}
};
我真正需要做的是插入Run
没有文字的内容。但是如果我这样做,当我使用带有初始文本(如“test”)的构造函数时,以这种方式插入一个 Run<Run FontWeight="bold" />
而不是<Run FontWeight="bold"></Run>.
我可以获得第二个(我需要的),然后我也可以将插入符号位置设置为新创建的运行。但后来我的 RTB 中有文本,这是我不想要的。我想在构造函数中设置文本,然后将文本设置为空,但如果我这样做,插入的内容Run
会再次恢复到第一个版本,我无法在Run
. 有没有办法实现这一点:run
在插入符号位置插入一个新的空白,文本样式为粗体,插入符号位置设置在这个新的运行中?
请注意,fds
仅设置了字符串,因此我可以在调试时将流文档视为 XAML 字符串。
解决方案
推荐阅读
- php - Bcrypt Codeigniter
- sql-server - 在 SSRS 报告中使用案例条件使用基于日期的计算
- sql-server - 将数据分成多列
- javascript - 选择选项后如何使用javascript隐藏和显示div?
- scala - 在 Scala 中将数据帧转换为 Spark mllib 矩阵
- java - 如何使信标保持配对模式,直到它超出 android 的范围?
- c - 当 ram 地址存储为 u32 时从 ram 内存中获取值
- ios - 仅当特定 ViewController 在前台时 iOS Swift 调用函数
- ios - 从 UITableView 中删除自定义视图
- c# - 'type' 是一个变量,但用作类型