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的嵌套等等,更多的還須要不斷的去發掘。但願本文能給你們帶來幫助,感謝閱讀!

源碼

相關文章
相關標籤/搜索