由于公司涉及到聊天对话框的功能,就想到了RichTextBox,查阅相关资料,总结下:

一、RichTextBox的内容相关的类

1.1RichTextBox的内容结构

RichTexBox是个可编辑控件,可编辑我们很容易想到word的可编辑,在word里面我们经常会新建一个Document,然后一段一段的编写,有的时间会插入图片,或者是特殊的文本。同样RichTextBox也是一个以Document为主体的一个控件,Document也有段落(Paragraph),不过段落中是分为小片小片(Inline),我们可以理解为这些Inline被一条线串在段落(Paragragh)中。除此之外,还有些段落(BlockUIContainer)是只含有一个UI元素的,也即独立成段。下面给出其大致的内容结构。

1.2RichTextBox内容相关的类

FlowDocument中有个BlockCollection类型的Blocks属性,也就是“文档”包括的段落。主要有两种类型的Paragraph和BlockUIContainer两种类型的段落,其都继承自Block抽象类。下面介绍一下Paragraph的小弟们,从上图可以看出来小弟很多,其实都是和InLine有关,通常使用Run类表示文本,我们可以通过其属性类控制他的背景色,字体颜色,字体大小等。Hyperlink可以用来指定超链接。。。其中InlineContainer是有些不一样,其有个儿子是UIElement。看后缀名就知道BlockUIContainer和InlineContainer一定有些相似之处,相似的地方是BlockUIContainer也是有个儿子UIElement。当然一个是Inline类型,一个是Block类型。

光说不练,不是好汉,接下来就举几个例子来说明上面的类的特点:

1.3RichTextBox内容相关类的演示

下面我们就用wpf实现与RichtextBox内容相关的类的操作。先说一下需求,在“文档”上面写两端文字,一个是Paragraph类型的段落,一个是BlockContainer类型的段落。其中Paragraph中包括一个红色的文本Run、一个超链接Hyperlink,一个InlineContainer的内含有个TextBlock;BlockUIContainer含有一个图片以及图片说明。

//定义一个段落ParagraphParagraph paragraph = new Paragraph();//run Run run = new Run() { Text = "我是红色的Run", Background = new SolidColorBrush(Color.FromRgb(255, 0, 0)) }; paragraph.Inlines.Add(run); //Hyperlink Hyperlink hyperlink = new Hyperlink(); hyperlink.Inlines.Add("我是博客园主页的链接"); hyperlink.MouseLeftButtonDown += ((s, arg) => { Process proc = new Process(); proc.StartInfo.FileName = "http://www.cnblogs.com"; proc.Start(); }); paragraph.Inlines.Add(hyperlink); //InlineUIContainer InlineUIContainer inlineUIContainer = new InlineUIContainer() { Child = new TextBlock() { Text = "我是的TextBlock,哈哈" } }; paragraph.Inlines.Add(inlineUIContainer); rtb.Document.Blocks.Add(paragraph); //下面是BlockUIContainer部分 Grid grid = new Grid(); RowDefinition row1 = new RowDefinition(); grid.RowDefinitions.Add(row1); RowDefinition row2 = new RowDefinition(); grid.RowDefinitions.Add(row2); row2.Height = new GridLength(100); //定义图片,注意设置资源的类型,始终复制和嵌入 Image image = new Image() { Source = new BitmapImage(new Uri(("Images/vs.png"), UriKind.Relative)) }; image.Height = 30; image.SetValue(Grid.RowProperty, 0); grid.Children.Add(image); image.Visibility = Visibility.Visible; row2.SetBinding(RowDefinition.HeightProperty, new Binding("Height") { Source = image }); //定义说明 TextBlock block = new TextBlock(); block.Text = "我是图片说明"; block.SetValue(Grid.RowProperty, 1); grid.Children.Add(block); BlockUIContainer blockUIContainer = new BlockUIContainer(grid) ; rtb.Document.Blocks.Add(blockUIContainer);

show一下结果

二、RichTextBox的定位操作

首先给出定位操作的意思,就是在光标闪烁的地方操作。在看下面的文章时,我希望在我们心中有个word软件。下面主要介绍关于光标的位置和在光标的位置插入相应的元素。

2.1光标的位置

无论光标是否选中一段文字,都有可以获取rtb.Selection的开始位置(Start)和结束位置(End)。可以通过开始位置和结束位置来获取光标位置所在的段落(Paragraph)和父对象(Parent)。父对象其实也就是如果光标在run中间,获取到的就是Run,当选中的是TextBlock时,父对象就是Paragraph。这两个属性各有优略,段落可能获得空值,在操作的时间抛出空指针异常,但得到的类型确定(是属于Block类),父对象不会抛出空指针异常,但是其类型不确定。

2.2在光标处插入对象和替换对象

下面来看看相关内容类的构造函数:

Run:public Run(string text, TextPointer insertionPosition)Span:public Span(Inline childInline, TextPointer insertionPosition); public Span(TextPointer start, TextPointer end); Hypelink: public Hyperlink(Inline childInline, TextPointer insertionPosition); public Hyperlink(TextPointer start, TextPointer end); InlineContainer public InlineUIContainer(UIElement childUIElement, TextPointer insertionPosition); 

……以上我列出了几个非默认的构造类,其他的相关类,就不一一列出。从参数可以看出我们很容易的可以在光标处插入对象。下面只给出其代码片段:

TextPointer textPointer = rtb.Selection.Start;Run run = new Run("测试", textPointer);

接着是替换对象,我们想把选中的内容替换成指定的内容。下面我给出其实例:

//获取选中部分的开始位置
TextPointer textPointer = rtb.Selection.Start;
//在开始位置插入内容
Run run = new Run("测试", textPointer); //在插入内容的结尾到原来选中部分的结尾——原来选中部分的文字 清除掉 TextPointer pointer = run.ContentEnd; TextRange textRange = new TextRange(pointer, rtb.Selection.End); textRange.Text = ""; //如果使用下面的会把刚刚插入的内容一并删除 //rtb.Selection.Text = "";

对于有开始位置和结束位置的构造函数,可以使用相同的位置来构造,如下:

Hyperlink hypelink = new Hyperlink(textPointer, textPointer);

三、WPF中RichTextBox和工具栏的协同工作

WPF中RichTextBox可以与工具栏协同的命令:ApplicationCommands 和EditingCommands,在默认只有一个RichTextBox时,工具栏中的按钮的命令设置为系统命令时就会自动的把命令的目标设置为RichTextBox。下面给出一个实例:

<Grid> <Grid.RowDefinitions> <RowDefinition Height="1*"/> <RowDefinition Height="5*"/> </Grid.RowDefinitions> <ToolBarTray> <ToolBar> <Button Command="Undo">撤销</Button> <Button Command="EditingCommands.ToggleBold" ToolTip="Bold">B</Button> </ToolBar> </ToolBarTray> <RichTextBox Name="rtb" AcceptsTab="True" Grid.Row="1" Grid.ColumnSpan="4"></RichTextBox> <!--<Button x:Name="btnAddElement" Content="添加元素" Grid.Row="1" Click="btnAddElement_Click_1" Grid.Column="0" Margin="5"></Button>--> </Grid>

当点击撤销按钮时,RichTextBox会撤销操作,同样Bold会黑体操作。当然也可使用下面代码来显式指定按钮的命令目标。

<Style TargetType="{x:Type Button}" x:Key="ImageButtonStyle"> <Setter Property="CommandTarget" Value="{Binding ElementName=rtb}"></Setter> </Style>

四、RichTextBox的XAML转化成HTML以及HTML转化成XAML

在使用RichTextBox时,可能会遇到存储和显示不一致的问题,如在数据库里面是使用fck编辑的html格式,显示的时间要使用RichTextBox显示。或者是使用RichTextBox编辑的内容,要使用html显示。那么这样就会遇到转化问题,微软在这方面已经有为我们做好的类。下面给出链接:

https://github.com/stimulant/SocialStream/tree/master/XAMLConverter

以上转化针对简单的转化,或者是提供了思路,如果遇到特殊的自定义容器,还需要自己去添加。除上面的链接之外,很有必要给出下面两个方法。

//把richtextBox内容转成字符串形式            string strDoc=System.Windows.Markup.XamlWriter.Save(rtb.Document);              //上面的逆操作               StringReader stringReader = new StringReader(strDoc);               XmlReader xmlReader = XmlReader.Create(stringReader);               FlowDocument flowDocument = XamlReader.Load(xmlReader) as FlowDocument;

五、零碎知识点总结

1. 取得已被选中的内容:

(1)使用 RichTextBox.Document.Selection属性

(2)访问RichTextBox.Document.Blocks属性的“blocks”中的Text

2. 在XAML中增加内容给RichTextBox:

<RichTextBox IsSpellCheckEnabled="True">

<FlowDocument>

<Paragraph> <!-- 这里加上你的内容 -->

This is a richTextBox. I can <Bold>Bold</Bold>,

<Italic>Italicize</Italic>,

<Hyperlink>Hyperlink stuff</Hyperlink>

right in my document.

</Paragraph>

</FlowDocument>

</RichTextBox>

3. 缩短段间距,类似<BR>,而不是<P>

方法是使用Style定义段间距:

<RichTextBox>

<RichTextBox.Resources>

<Style TargetType="{x:Type Paragraph}">     

        <Setter Property="Margin" Value="0"/>   

        </Style>

</RichTextBox.Resources>

<FlowDocument>

<Paragraph>

This is my first paragraph... see how there is...

</Paragraph>

<Paragraph>

a no space anymore between it and the second paragraph?

</Paragraph>

</FlowDocument>

</RichTextBox>

4. 从文件中读出纯文本文件后放进RichTextBox或直接将文本放进RichTextBox中:
private void LoadTextFile(RichTextBox richTextBox, string filename)
{     richTextBox.Document.Blocks.Clear();  
using (StreamReader streamReader = File.OpenText(filename))
{         
Paragraph paragraph = new Paragraph();
paragraph.Text = streamReader.ReadToEnd();           
richTextBox.Document.Blocks.Add(paragraph);    
}
}
private void LoadText(RichTextBox richTextBox, string txtContent)
{    
richTextBox.Document.Blocks.Clear();
Paragraph paragraph = new Paragraph();     
paragraph.Text = txtContent;    
richTextBox.Document.Blocks.Add(paragraph);
}
5. 取得指定RichTextBox的内容:
private string GetText(RichTextBox richTextBox)
{        
TextRange textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);        
return textRange.Text;
}
6. 将RTF (rich text format)放到RichTextBox中:
private static void LoadRTF(string rtf, RichTextBox richTextBox)
{            
if (string.IsNullOrEmpty(rtf))
{                
throw new ArgumentNullException();    
}           
TextRange textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);     
using (MemoryStream rtfMemoryStream = new MemoryStream())
{                
using (StreamWriter rtfStreamWriter = new StreamWriter(rtfMemoryStream))
{                     rtfStreamWriter.Write(rtf);   
rtfStreamWriter.Flush();    
rtfMemoryStream.Seek(0, SeekOrigin.Begin);
//Load the MemoryStream into TextRange ranging from start to end of RichTextBox.  
textRange.Load(rtfMemoryStream, DataFormats.Rtf);       
}            
}        
}
7. 将文件中的内容加载为RichTextBox的内容
private static void LoadFile(string filename, RichTextBox richTextBox)  
{           
if (string.IsNullOrEmpty(filename))
{              
throw new ArgumentNullException();            
}           
if (!File.Exists(filename))
{                
throw new FileNotFoundException();   
}   
using (FileStream stream = File.OpenRead(filename))
{              
TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);   
string dataFormat = DataFormats.Text;         
string ext = System.IO.Path.GetExtension(filename);              
if (String.Compare(ext, ".xaml",true) == 0)
{               
dataFormat = DataFormats.Xaml;     
}       
else if (String.Compare(ext, ".rtf", true) == 0)
{                   
dataFormat = DataFormats.Rtf;         
}           
documentTextRange.Load(stream, dataFormat);       
}              
}
8. 将RichTextBox的内容保存为文件:
private static void SaveFile(string filename, RichTextBox richTextBox)
{            
if (string.IsNullOrEmpty(filename))
{                
throw new ArgumentNullException();       
}
using (FileStream stream = File.OpenWrite(filename))
{
TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
string dataFormat = DataFormats.Text;
string ext = System.IO.Path.GetExtension(filename);
if (String.Compare(ext, ".xaml", true) == 0)
{
dataFormat = DataFormats.Xaml;
}                
else if (String.Compare(ext, ".rtf", true) == 0)
{
dataFormat = DataFormats.Rtf;                
}                 documentTextRange.Save(stream, dataFormat);
}
}

转载于:https://www.cnblogs.com/fuchongjundream/p/3889469.html

WPF RichTextBox相关总结相关推荐

  1. WPF RichTextBox自动调整高度

    WPF RichTextBox自动调整高度 原文:WPF RichTextBox自动调整高度 大概两年前的这个时间段,当时做项目遇到了一个问题:环境VS2005.WinForm,需要RichTextB ...

  2. WPF RichTextBox将FlowDocument节点元素移动到可视范围

    默认情况下,当更新WPF RichTextBox时,系统不会自动将更新的内容展示到可视范围中,所以需要通过RichTextBox的一个方法ScrollToVerticalOffset来设置当前显示的位 ...

  3. WPF RichTextBox 总结

    转自 https://www.cnblogs.com/fuchongjundream/p/3889469.html 一.RichTextBox的内容相关的类 1.1RichTextBox的内容结构 R ...

  4. WPF TreeView 相关技巧

    WPF 中的 TreeView 相关实用技巧如下 响应 TreeViewItem 的双击事件 这是一个较怪异的问题,如果在 TreeView 的 MouseDoubleClick 中去处理 Selec ...

  5. WPF Popup 相关内容

    引自:http://technet.microsoft.com/zh-cn/magazine/bb613596(VS.90).aspx http://www.th7.cn/Program/WPF/20 ...

  6. WPF RichTextBox 控件常用方法和属性

    以下内容转自 http://blog.csdn.net/yulongguiziyao/article/details/25330551. 1. 取得已被选中的内容: (1)使用 RichTextBox ...

  7. wpf richtextbox 存储到数据库并显示

    做一个项目,需要图文一起存入数据库,在网上浏览了很久.终于实现了在RICHTEXTBOX里面和数据库读写图文的方法. 存入数据库. public string toxaml()         {   ...

  8. WPF RichTextBox的Document属性的序列化与反序列化

    序列化: string strDocument = System.Windows.Markup.XamlWriter.Save(m_RichTextBox.Document); 保存成字符串的形式 反 ...

  9. WPF RichTextBox·绑定数据

    一. 添加BinBindableRichTextBox类 public class BindableRichTextBox : RichTextBox{public new FlowDocument ...

最新文章

  1. 数据中心布线系统构成及不同规模范例
  2. ALGO-185 Trash Removal
  3. Linux生产环境CPU占用过高排查步骤
  4. 如何观察JS的事件队列的执行划分
  5. python中什么是数据驱动_携程大牛谈自动化测试里的数据驱动和关键字驱动思路的理解...
  6. vector容器,容量和大小的操作
  7. 瑞友企业私有云显示连接负载服务器错误,荣誉资质 | 瑞友天翼-应用虚拟化|远程接入|桌面虚拟化|国内虚拟化整体解决方案领导者...
  8. linux系统ss命令详解,linux 下 ss命令详解
  9. 基金与私募基金概念解析:共同基金、单位信托、投资信托计划、券商集合理财、基金专户理财
  10. java开发——发送短信功能
  11. 【职场篇】游戏开发社招求职面试指南③——面试总结
  12. 交叉编译OpenCV3.4.1报错
  13. [UnityC#事件委托]对委托事件的学习与实践
  14. python获取Q群的信息数据100%用得到【已开源】
  15. 点到直线的距离,垂足,对称点,两点所成的直线方程
  16. 【转载】中国特色的免费游戏:下流下贱下作!
  17. 半双工 Wi-Fi 无线局域网
  18. daemontools安装及使用技巧
  19. matlab图像导数求积分_第二讲matlab求微分方程导数积分
  20. 有道云笔记登录失败,解决办法

热门文章

  1. 信息服务器为什么选择在贵州,为啥云服务器在贵州
  2. android布局属性,Android 布局学习之——LinearLayout属性baselineAligned的作用及baseline...
  3. Linux中wait接口用于延时,linux2.6驱动编写参考
  4. xml html 转化为字符串,XSLT:将字符串解析为XML节点集(concret:将HTML-String转换为节点集)?...
  5. StringBuilder 和 String拼接10万个字符串的速度测试差别太大了
  6. JDBC 连接MYSQL数据库
  7. Tomcat服务器性能优化
  8. 机器学习问题总结(01)
  9. 牛客网C++面经 类和数据抽象
  10. 区块链中涉及到密码学的场景