WPF RichTextBox相关总结

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

一、RichTextBox的内容相关的类

1.1RichTextBox的内容结构

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

image

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一下结果

image

二、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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 内置方法赋值_Python内置数据结构之字符串str

1. 数据结构回顾所有标准序列操作(索引、切片、乘法、成员资格检查、长度、最小值和最大值)都适用于字符串&#xff0c;但是字符串是不可变序列&#xff0c;因此所有的元素赋值和切片赋值都是非法的。>>> website http://www.python.org>>> website[-3:] c…

以下是关于ASP.NET中保存各种信息的对象的比较,理解这些对象的原理,对制作完善的程序来说是相当有必要的(摘至互联网,并非原创--xukunping)...

在ASP.NET中&#xff0c;有很多种保存信息的对象.例如:APPlication,Session,Cookie,ViewState和Cache等,那么它们有什么区别呢?每一种对象应用的环境是什么? 为了更清楚的了解,我们总结出每一种对象应用的具体环境,如下表所示: 方法信息量大小保存时间应用范围保存位置App…

实现每个点赞用户点击的带属性的字符串

2019独角兽企业重金招聘Python工程师标准>>> #pragma mark - 点击各个点赞用户-(void)setClicked:(TweetCell *)cell andOSCTweet:(OSCTweet *)tweet {NSMutableAttributedString *attributedString [[NSMutableAttributedString alloc] initWithString:tweet.like…

xampp php5.6 7.1共存,New XAMPP with PHP 7.2.8, 7.1.20, 7.0.31 5.6.37

嗨&#xff0c;阿帕奇的朋友们&#xff01;We just released new versions of XAMPP for all platforms with the latest PHP versions: 7.2.8, 7.1.20, 7.0.31 & 5.6.37.您可以下载这些新版本http://www.apachefriends.org/download.html.7.2.8 / 7.1.20 / 7.0.31 / 5.6.3…

基于.net开发chrome核心浏览器【四】

原文:基于.net开发chrome核心浏览器【四】一&#xff1a; 上周去北京出差&#xff0c;给国家电网的项目做架构方案&#xff0c;每天都很晚睡&#xff0c;客户那边的副总也这样拼命工作。 累的不行了&#xff0c;直接导致第四篇文章没有按时发出来。 希望虚心学习1&#xff0c;小…

php5.6 pdo.dll 没有,php5.6没有pdo怎么办

php5.6没有pdo是因为在php5.6中php已经内置了pdo功能&#xff0c;只需要在php.ini文件中将“extensionphp_pdo_firebird.dll”等配置项打开即可。推荐&#xff1a;《PHP视频教程》php5.6中没有php.pdo.dll文件我下载的php 5.6要使用pdo模块&#xff0c;但是通过百度发现发现没有…

网页的背景图片代码

网页背景图片代码1.(最普遍类) <style>body{background-image:url(logo.gif);background-repeat:no-repeat;background-position:center}</style> 说明:以上代码为网页背景图片固定代码&#xff01;网页背景图片固定代码&#xff0c;这样&#xff0c;当向下拉网页时…

andriod 新建 Activity_ Form (详细设置)

参考&#xff1a; Starting Another Activity 去创建Activity New->Other->Android->Android Activity->BlankActivity&#xff1a; 输入对应的信息&#xff1a; 创建完毕后&#xff0c;可以看到新建了对应的 src下面的java文件 layout下面的xml 等等&#xff1a; …

php laypage,layui laypage组件常见用法总结

laypage 的使用非常简单&#xff0c;指向一个用于存放分页的容器&#xff0c;通过服务端得到一些初始值&#xff0c;即可完成分页渲染。核心方法&#xff1a; laypage.render(options) 来设置基础参数。一、laypage的常用基础参数layui.use([laypage], function () {laypage l…

Swift标识符和关键字

任何一种计算机语言都离不开标识符和关键字&#xff0c;下面我们将详细介绍Swift标识符和关键字。 标示符 标识符就是给变量、常量、方法、函数、枚举、结构体、类、协议等指定的名字。构成标识符的字母均有一定的规范&#xff0c;Swift语言中标识符的命名规则如下&#xff1a;…

nyist 17 -----记忆式搜索------Accept

//记忆式搜索 #include <iostream>#include<stdio.h>#include<string.h>using namespace std;char a[10002];int b[10002];int n,ans;int f(int x){ int i,t; if(b[x]>0) return b[x]; b[x]1; for(i0;i<x-1;i) { tf(i); if(a[i]<a[x] && b[…

asp.net matlab,ASP.NET与MATLAB混合编译以及数据传递【更新中】

本帖最后由 yinbo20081314 于 2015-5-20 00:35 编辑在VS环境的项目中&#xff0c;首先需要引用以下dll才能开启MATLAB混编。【引用1】MatlabApplication(Version 8.1) Type Library 1.0a1.jpg (42.85 KB, 下载次数: 9)2015-5-20 00:16 上传【引用2】在MATLAB安装地址下可以找到…

01背包 模板1 2 总结

物品质量 w[0] w[1] w[2] ....... w[n] 背包容量c T 物品价值 v[0] v[1] v[2] ....... v[n] 物品种类 n N &#xff08;一&#xff09;设DP(x,y) 表示 从前x项物品中 取出装入 体积为y的背包 的 物品的最…

matlab暂停音频,matlab 中的实时音频

matlab 中的实时音频音频系统工具箱™针对实时音频处理进行了优化. audioDeviceReader, audioDeviceWriter, audioPlayerRecorder,dsp.AudioFileReader 和 dsp.AudioFileWriter 器是为流式传输多通道音频而设计的, 它们提供了必要的参数, 以便您可以在吞吐量和延迟之间进行权衡…

js数组操作

2019独角兽企业重金招聘Python工程师标准>>> 1、数组的创建 var arrayObj new Array(); //创建一个数组 var arrayObj new Array([size]); //创建一个数组并指定长度&#xff0c;注意不是上限&#xff0c;是长度 var arrayObj new Array([element0[, element1[…

用webstorm自动编译less产出css和sourcemap

css产出sourcemap有什么用呢&#xff0c;可能大家要问这个问题了。 请移步这里 https://developers.google.com/chrome-developer-tools/docs/css-preprocessors?hlzh-CN 在chrome中我们通过sourcemap可以直接调试less源文件文件&#xff0c;这是一个非常强大的功能。 下面由我…

远近旋转球体

2019独角兽企业重金招聘Python工程师标准>>> static int day 20; void mydisplay(void) {int a clock();glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清空颜色缓存与深度缓存glMatrixMode(GL_PROJECTION);//接下来要进行的操作…

iOS开发UI篇—CALayer简介

一、简单介绍在iOS中&#xff0c;你能看得见摸得着的东西基本上都是UIView&#xff0c;比如一个按钮、一个文本标签、一个文本输入框、一个图标等等&#xff0c;这些都是UIView。 其实UIView之所以能显示在屏幕上&#xff0c;完全是因为它内部的一个图层&#xff0c;在创建UIVi…

php 多进程 常驻内存,PHP 多进程与信号中断实现多任务常驻内存管理 [Master/Worker 模型]...

本文章基于pcntl扩展做的多进程测试。进程调度策略父子进程的调度由操作系统来负责&#xff0c;具体先调度子进程还是父进程由系统的调度算法决定&#xff0c;当然可以在父进程加上延时或是调用进程回收函数pcntl_wait可以先让子进程先运行&#xff0c;进程回收的目的是释放进程…

RPG的错排

RPG的错排 Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 25 Accepted Submission(s) : 14 Problem Description今年暑假杭电ACM集训队第一次组成女生队,其中有一队叫RPG,但做为集训队成员之一的野骆驼竟然不知道…