由于公司涉及到聊天对话框的功能,就想到了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. 简单的proxy之TinyHTTPProxy.py

    简单的proxy之TinyHTTPProxy.py 如果是在外企工作的话,可以访问美国的机器,这样就可以在美国的机器上为自己装个proxy,然后本地就可以很容易的使用proxy来上网了. TinyHT ...

  2. api日常总结

    异步加载JS和CSS <script type="text/javascript"> (function () { var s = document.createEle ...

  3. ASP.NET Web API中通过URI显示实体中的部分字段

    有时候我们可能不想显示某个实体中的所有字段.比如客户端发出如下请求: locaohost:43321/api/groups/1/items?fields=idlocaohost:43321/api/g ...

  4. Maven deploy部署jar到远程私服仓库

    一.配置私服账号密码 修改maven配置文件,在$MAVEN_HOME/conf/setting.xml中增加如下配置: 注意,这里配置的id为releases何snapshots,当然可以改为其他, ...

  5. Go语言之高级篇beego框架之Controller

    一.Controller 控制器 Controller等同于Django里的view,处理逻辑都是在Controller里面完成的,下面就写一个最简单的Controller.写controller的时 ...

  6. volitile关键字

    1.volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修 ...

  7. dubbo服务启动的方式

    dubbo服务启动的方式: 1.dubbo自带的脚本, 2.直接用main方法启动dubbo的spring容器,参见dubbo-test里的各个例子 3.dubbo的spring boot start ...

  8. 用命令让vbox的虚拟硬盘文件转换成vmware的vmdk

    VirtualBox的生成备份功能只是个系统还原点 这个生成备份功能备份速度非常快,其实它并不是备份,而是相当于xp系统中的建立系统还原点.但是要注意的是如果你的虚拟硬盘文件(***.vdi)在别的V ...

  9. Type Call requires API level 11 (current min is 8)解决办法

    解决办法: 1:project-->clean.. 2:右键工程-->Android Tools-->clean lint markers 3:修改AndroidManifest.x ...

  10. sed学习[参考转载]

    一.选项与参数: -n :使用安静(silent)模式.在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上.但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者 ...