WPF RichTextBox相关总结
????由于公司涉及到聊天對話框的功能,就想到了RichTextBox,查閱相關(guān)資料,總結(jié)下:
一、RichTextBox的內(nèi)容相關(guān)的類
1.1RichTextBox的內(nèi)容結(jié)構(gòu)
RichTexBox是個可編輯控件,可編輯我們很容易想到word的可編輯,在word里面我們經(jīng)常會新建一個Document,然后一段一段的編寫,有的時間會插入圖片,或者是特殊的文本。同樣RichTextBox也是一個以Document為主體的一個控件,Document也有段落(Paragraph),不過段落中是分為小片小片(Inline),我們可以理解為這些Inline被一條線串在段落(Paragragh)中。除此之外,還有些段落(BlockUIContainer)是只含有一個UI元素的,也即獨立成段。下面給出其大致的內(nèi)容結(jié)構(gòu)。
1.2RichTextBox內(nèi)容相關(guān)的類
FlowDocument中有個BlockCollection類型的Blocks屬性,也就是“文檔”包括的段落。主要有兩種類型的Paragraph和BlockUIContainer兩種類型的段落,其都繼承自Block抽象類。下面介紹一下Paragraph的小弟們,從上圖可以看出來小弟很多,其實都是和InLine有關(guān),通常使用Run類表示文本,我們可以通過其屬性類控制他的背景色,字體顏色,字體大小等。Hyperlink可以用來指定超鏈接。。。其中InlineContainer是有些不一樣,其有個兒子是UIElement。看后綴名就知道BlockUIContainer和InlineContainer一定有些相似之處,相似的地方是BlockUIContainer也是有個兒子UIElement。當(dāng)然一個是Inline類型,一個是Block類型。
光說不練,不是好漢,接下來就舉幾個例子來說明上面的類的特點:
1.3RichTextBox內(nèi)容相關(guān)類的演示
下面我們就用wpf實現(xiàn)與RichtextBox內(nèi)容相關(guān)的類的操作。先說一下需求,在“文檔”上面寫兩端文字,一個是Paragraph類型的段落,一個是BlockContainer類型的段落。其中Paragraph中包括一個紅色的文本Run、一個超鏈接Hyperlink,一個InlineContainer的內(nèi)含有個TextBlock;BlockUIContainer含有一個圖片以及圖片說明。
//定義一個段落ParagraphParagraph 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); //定義圖片,注意設(shè)置資源的類型,始終復(fù)制和嵌入 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一下結(jié)果
二、RichTextBox的定位操作
首先給出定位操作的意思,就是在光標(biāo)閃爍的地方操作。在看下面的文章時,我希望在我們心中有個word軟件。下面主要介紹關(guān)于光標(biāo)的位置和在光標(biāo)的位置插入相應(yīng)的元素。
2.1光標(biāo)的位置
無論光標(biāo)是否選中一段文字,都有可以獲取rtb.Selection的開始位置(Start)和結(jié)束位置(End)。可以通過開始位置和結(jié)束位置來獲取光標(biāo)位置所在的段落(Paragraph)和父對象(Parent)。父對象其實也就是如果光標(biāo)在run中間,獲取到的就是Run,當(dāng)選中的是TextBlock時,父對象就是Paragraph。這兩個屬性各有優(yōu)略,段落可能獲得空值,在操作的時間拋出空指針異常,但得到的類型確定(是屬于Block類),父對象不會拋出空指針異常,但是其類型不確定。
2.2在光標(biāo)處插入對象和替換對象
下面來看看相關(guān)內(nèi)容類的構(gòu)造函數(shù):
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);……以上我列出了幾個非默認(rèn)的構(gòu)造類,其他的相關(guān)類,就不一一列出。從參數(shù)可以看出我們很容易的可以在光標(biāo)處插入對象。下面只給出其代碼片段:
TextPointer textPointer = rtb.Selection.Start;Run run = new Run("測試", textPointer);接著是替換對象,我們想把選中的內(nèi)容替換成指定的內(nèi)容。下面我給出其實例:
//獲取選中部分的開始位置 TextPointer textPointer = rtb.Selection.Start; //在開始位置插入內(nèi)容 Run run = new Run("測試", textPointer); //在插入內(nèi)容的結(jié)尾到原來選中部分的結(jié)尾——原來選中部分的文字 清除掉 TextPointer pointer = run.ContentEnd; TextRange textRange = new TextRange(pointer, rtb.Selection.End); textRange.Text = ""; //如果使用下面的會把剛剛插入的內(nèi)容一并刪除 //rtb.Selection.Text = "";?
對于有開始位置和結(jié)束位置的構(gòu)造函數(shù),可以使用相同的位置來構(gòu)造,如下:
Hyperlink hypelink = new Hyperlink(textPointer, textPointer);
三、WPF中RichTextBox和工具欄的協(xié)同工作
WPF中RichTextBox可以與工具欄協(xié)同的命令:ApplicationCommands 和EditingCommands,在默認(rèn)只有一個RichTextBox時,工具欄中的按鈕的命令設(shè)置為系統(tǒng)命令時就會自動的把命令的目標(biāo)設(shè)置為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>當(dāng)點擊撤銷按鈕時,RichTextBox會撤銷操作,同樣Bold會黑體操作。當(dāng)然也可使用下面代碼來顯式指定按鈕的命令目標(biāo)。
<Style TargetType="{x:Type Button}" x:Key="ImageButtonStyle"> <Setter Property="CommandTarget" Value="{Binding ElementName=rtb}"></Setter> </Style>四、RichTextBox的XAML轉(zhuǎn)化成HTML以及HTML轉(zhuǎn)化成XAML
在使用RichTextBox時,可能會遇到存儲和顯示不一致的問題,如在數(shù)據(jù)庫里面是使用fck編輯的html格式,顯示的時間要使用RichTextBox顯示。或者是使用RichTextBox編輯的內(nèi)容,要使用html顯示。那么這樣就會遇到轉(zhuǎn)化問題,微軟在這方面已經(jīng)有為我們做好的類。下面給出鏈接:
https://github.com/stimulant/SocialStream/tree/master/XAMLConverter
以上轉(zhuǎn)化針對簡單的轉(zhuǎn)化,或者是提供了思路,如果遇到特殊的自定義容器,還需要自己去添加。除上面的鏈接之外,很有必要給出下面兩個方法。
????????? //把richtextBox內(nèi)容轉(zhuǎn)成字符串形式 ?????????? 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;
五、零碎知識點總結(jié)
1. 取得已被選中的內(nèi)容:
(1)使用 RichTextBox.Document.Selection屬性
(2)訪問RichTextBox.Document.Blocks屬性的“blocks”中的Text
2. 在XAML中增加內(nèi)容給RichTextBox:
<RichTextBox IsSpellCheckEnabled="True"> ??
<FlowDocument> ???????
<Paragraph> <!-- 這里加上你的內(nèi)容 --> ????
????? 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. 從文件中讀出純文本文件后放進(jìn)RichTextBox或直接將文本放進(jìn)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的內(nèi)容: 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. 將文件中的內(nèi)容加載為RichTextBox的內(nèi)容 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的內(nèi)容保存為文件: 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); } }
?
轉(zhuǎn)載于:https://www.cnblogs.com/fuchongjundream/p/3889469.html
總結(jié)
以上是生活随笔為你收集整理的WPF RichTextBox相关总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis报错:redis.except
- 下一篇: DateUtils常用方法