我有一个WPF RichTextBox
,带有一些用于文本样式的标准按钮。因为它们都应该以相同的方式工作,所以我将使用从现在开始使文本变为粗体的示例。
因此,我的目标是,用户可以单击粗体按钮,然后,无论此时插入符号的位置,他编写的文本都将以粗体显示。
必须在流程文档的内联中设置样式(因为我必须将包括样式在内的整个文本作为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"
>
</ComboBox>
<ToggleButton
x:Name="bold"
Content="B"
Margin="0,5,2"
Width="30">
</ToggleButton>
<ToggleButton
x:Name="italic"
Content="I"
Margin="0,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"
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
,不带任何文本。但是,如果执行此操作,则会以<Run FontWeight="bold" />
而不是<Run FontWeight="bold"></Run>.
的方式插入运行
当我将构造函数与诸如“ test”之类的初始文本一起使用时,我可以获得第二个(我需要的),然后还可以将插入符号的位置设置为新创建的Run。但是然后我在我的实时出价中输入了我不想要的文本。我曾考虑过在构造函数中设置文本,然后再将文本设置为空,但是如果这样做,插入的Run
会再次恢复为第一个版本,因此无法设置{{1}内的插入符号位置}。
有没有一种方法可以实现:在插入符位置插入一个新的空Run
,文字样式为 bold ,并在此新行程内设置插入符位置?
请注意,run
字符串仅被设置,因此在调试时我可以将流程文档视为XAML字符串。