由于公司涉及到聊天对话框的功能,就想到了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含有一个图片以及图片说明。

//定义一个段落Paragraph
Paragraph 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可以与工具栏协同的命令:ApplicationCommandsEditingCommands,在默认只有一个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);
            }
        }

WPF RichTextBox相关总结的更多相关文章

  1. WPF RichTextBox自动调整高度

    原文:WPF RichTextBox自动调整高度 大概两年前的这个时间段,当时做项目遇到了一个问题:环境VS2005.WinForm,需要RichTextBox根据内容自动调整高度.当时用了各种方法都 ...

  2. WPF RichTextBox 禁止换行

    原文:WPF RichTextBox 禁止换行 这个问题困扰了好久,进过不断的努力,终于解决了           <RichTextBox Margin="0,44,10,0&quo ...

  3. WPF RichTextBox 当前光标后一个字符是文档的第几个字符

    WPF RichTextBox 当前光标后一个字符是文档的第几个字符 运行环境:Win10 x64, NetFrameWork 4.8, 作者:乌龙哈里,日期:2019-05-05 参考: TextP ...

  4. WPF RichTextBox读取存储文本的方法和常用属性

    1. 取得已被选中的内容: (1)使用 RichTextBox.Document.Selection属性(2)访问RichTextBox.Document.Blocks属性的“blocks”中的Tex ...

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

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

  6. WPF-20:richtextbox相关操作(转)

    WPF中的richtextbox与winform中的richtextbox的使用不同,看看下面的基本操作: 一.取出richTextBox里面的内容  (1)将richTextBox的内容以字符串的形 ...

  7. WPF RichTextBox 做内容展示框 滚动条控制判定是否阅读完成

    一.项目背景: 最近,做项目,因为是金融项目,客户登录交易的时候,有一个提示框,就是告知客户要“入市需谨慎”等等,想必大家都遇到这样的场景,当然,这种提示是没人会看的,不过作为交易所,这样的提示又必不 ...

  8. WPF RichTextbox

    WPFTextBoxAutoComplete AvalonEdit WPF SyntaxHighlightBox   WinForm 下的 Fast Colored TextBox for Synta ...

  9. WPF RichTextBox,关键字搜索,样式改变,超链接替换,图文混排

    RichTextBox 只是一个控件,表示对 FlowDocument 对象执行操作的丰富编辑控件.它所承载的内容由其 Document 属性来呈现. Document 是一个 FlowDocumen ...

随机推荐

  1. [leetcode]Rotate List @ Python

    原题地址:https://oj.leetcode.com/problems/rotate-list/ 题意: Given a list, rotate the list to the right by ...

  2. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二十九):推送avro格式数据到topic,并使用spark structured streaming接收topic解析avro数据

    推送avro格式数据到topic 源代码:https://github.com/Neuw84/structured-streaming-avro-demo/blob/master/src/main/j ...

  3. PAM 認 證 模 組

    作者:陳柏菁 E-mail 作用:限制哪些用户或者组可以从哪里登陆,或者可以建立/etc/nologin立即阻止一般用户登陆,限制 user可以使用的资源.例如cpu,文件,登陆数量,某些服务的登陆时 ...

  4. Java通过JNI调用C++程序

    JNI是Java Native Interface的缩写,中文为JAVA本地调用.使用JNI可以很方便的用我们的Java程序调用C/C++程序.很多时候,某些功能用Java无法实现,比如说涉及到底层驱 ...

  5. SQL与MySQL基本

    一:概念辨析 数据库(database):是一种保存有组织的数据的容器. 数据库软件(DBMS):使用DBMS操作数据库.访问数据库. SQL:结构化查询语言,专门用来与数据库通信的语言.几乎所有DB ...

  6. VTK拾取网格模型上的可见点

    消隐与Z-Buffer 使用缓冲器记录物体表面在屏幕上投影所覆盖范围内的全部像素的深度值,依次访问屏幕范围内物体表面所覆盖的每一像素,用深度小(深度用z值表示,z值小表示离视点近)的像素点颜色替代深度 ...

  7. fiddler展示serverIP方法

    转载自:http://www.xuanfengge.com/fiddler-displays-the-set-ip-method.html 前言 由于web前端在多个环境中开发,需要经常更换host, ...

  8. 拯救者y720 双显卡, nvidia 1060 ,Ubuntu16.04 安装 Nvidia 显卡驱动

    为了能够记录,下次可以有参考的东西,就记录如此 多谢网上大牛的帖子,我都是安装您们的才顺利的一次性,无黑屏现象的完成了安装 1. 参考: 1.secure boot option ( 开机进入bios ...

  9. 前后分离模型之封装 Api 调用

    Ajax 和异步处理 调用 API 访问数据采用的 Ajax 方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异步过 ...

  10. SNF开发平台WinForm-平板拍照及扫描二维码功能

    在我们做项目的时候,经常会有移动平板处理检验,审核等,方便移动办公.这时就需要在现场拍照上传问题,把当场问题进行上传,也有已经拍完照的图片或加工过的图片进行上传.还有在车间现场一体机,工控机 这种产物 ...