由于公司涉及到聊天对话框的功能,就想到了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. 第二章 flex输入输出结构

    对于一个词法分析程序,一般读取文件或者终端 一个默认lex程序大致看上去像这样 YY_BUFFER_STATE bp; extern FILE* yyin; ... whatever the prog ...

  2. IBM Thread and Monitor Dump Analyzer for Java解决生产环境中的性能问题

    这个工具的使用和 HeapAnalyzer 一样,非常容易,同样提供了详细的 readme 文档,这里也简单举例如下: #/usr/java50/bin/java -Xmx1000m -jar jca ...

  3. 手机号是SIM卡的号呢,还是买手机时就带的

    可以用原来的号码!把原来的卡装在新手机里就可以了,你的号码没有改变! 手机的号是由sim卡来决定的! 但是卡上的号码显示的是卡的一些信息! 你不用去理会它! 全文:http://iask.sina.c ...

  4. 阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结

    2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker(Bugly sdk也集成Tikner ...

  5. 深入学习 FutureTask

    原文出处: 天凉好个秋 第一部分:What 在Java中一般通过继承Thread类或者实现Runnable接口这两种方式来创建多线程,但是这两种方式都有个缺陷,就是不能在执行完成后获取执行的结果,因此 ...

  6. 你真的会用Gson吗?Gson使用指南(3)

    原文出处: 怪盗kidou 注:此系列基于Gson 2.4. 本次的主要内容: 字段过滤的几种方法 基于@Expose注解 基于版本 基于访问修饰符 基于策略(作者最常用) POJO与JSON的字段映 ...

  7. Implement strStr() leetcode java

    题目: Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if ...

  8. angularjs使用ui-router切换视图, 自动滚动到顶部

    ui-view Examples for autoscroll: <ui-view autoscroll/> <!-- If autoscroll present with no e ...

  9. 为Docker容器设置http代理

    以下内容复制自:传送门 ,可以直接去该地址查看. HTTP/HTTPS proxy The Docker daemon uses the HTTP_PROXY, HTTPS_PROXY, and NO ...

  10. WineBottler for Mac(Mac 运行 exe 程序工具)安装

    1.软件简介    WineBottler 是 macOS 系统上一款模拟 Windows 环境的工具,让你能够在 Mac 上安装 Windows 软件,类似于知名的 Crossover,但 Wine ...