WPF/Silverlight中的RichTextBox总结

在WPF或者是在Silverlight中有个很是强大的能够编辑的容器控件RichTextBox,有的时间会采起该控件来做为编辑控件。鉴于这方面的文章很少,因此想把他的一些用法总结一些,以供你们参考。html

1、RichTextBox的内容相关的类

1.1RichTextBox的内容结构

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

image

只有图,没有说明,你们仍是不能很好的认识它,下面就介绍一下各个块。github

1.2RichTextBox内容相关的类

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

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

1.3RichTextBox内容相关类的演示

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

//定义一个段落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一下结果函数

image

2、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);

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

4、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;

5、总结

本文主要介绍RichTextBox的经常使用知识点,先简单介绍了其结构,接着介绍了能够放在RichTextBox里面的部分元素的插入和替换。同时也简单的提了一下wpf中工具栏和richtextBox的协同,最后给出了html和xaml的转化。固然RichTextBox的功能不止这些,例如在Blocks中还能够添加List(列表元素),以及List的嵌套等等,更多的还须要不断的去发掘。但愿本文能给你们带来帮助,感谢阅读!

源码

相关文章
相关标签/搜索