Binding and styling text to a RichTextBox in WPF
来源:互联网 发布:上海数据交易中心 福利 编辑:程序博客网 时间:2024/05/21 07:58
The RichTextBox
in WPF is a great tool for dealing with text that needs to be styled (such as syntax highlighting) but it's not so great when it comes to allowing us to bind and edit text on the fly.
I got a feature request from our product manager to change the colour of certain text within a TextBox
to match a legacy application. It turns out it is not as straight forward as you might expect.
We have text in an SQL database like this:
this is a title:.\r\n\r\nThis is a normal line\r\n\r\nthis is another title:.\r\n
You can see that the titles end with “:.
” so all we need to do is pull out these lines and make them (in my case) blue.
The problem is that this text is on an object that my previous TextBox
was able to bind its Text
property to with ease, but the RichTextBox
has no text
property as it displays a flow document. OK, I thought, I will just bind thetext
to the document
as follows:
<RichTextBox IsReadOnly=”True” Document=”{Binding ElementName=ViewType, Path=SelectedItem.Tag />
This doesn't work because the Document
property is not a Dependency Property and therefore cannot be bound to. So BindableRichTextBox
here I come. I created a very simple control so that I could bind to the Document
property. In doing this, I discovered that the Document
property expects a FlowDocument
as its content so I had to convert my text string to a flow document with the relevant parts highlighted. I used a converter to spit out theFlowDocument
with the correctly formatted text on a per line basis.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture){ FlowDocument doc = new FlowDocument(); string s = value as string; if (s != null) { using (StringReader reader = new StringReader(s)) { string newLine; while ((newLine = reader.ReadLine()) != null) { Paragraph paragraph = null; if (newLine.EndsWith(":.")) { paragraph = new Paragraph(new Run(newLine.Replace(":.", string.Empty))); paragraph.Foreground = new SolidColorBrush(Colors.Blue); paragraph.FontWeight = FontWeights.Bold; } else { paragraph = new Paragraph(new Run(newLine)); } doc.Blocks.Add(paragraph); } } } return doc;}
This simply takes the string
and reads it line by line. If we have the desired characters at the end of a line (“:.
”), then we make the line blue and bold and remove the characters, otherwise we just add the text. Each line is added as a paragraph so to reduce the space between each one I added the following to the control declaration in the XAML:
<RichTextBox.Resources><Style TargetType=”{x:Type Paragraph}”><Setter Property=”Margin” Value=”0?/></Style></RichTextBox.Resources>
This simply removes the margin from each paragraph.
The final part of the puzzle is the control that allows binding. This is a simple case of adding a dependency property onto a new control that inherits from RichTextBox
.
public class BindableRichTextBox : RichTextBox{ public static readonly DependencyProperty DocumentProperty = DependencyProperty.Register("Document", typeof(FlowDocument), typeof(BindableRichTextBox), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDocumentChanged))); public new FlowDocument Document { get { return (FlowDocument)this.GetValue(DocumentProperty); } set { this.SetValue(DocumentProperty, value); } } public static void OnDocumentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { RichTextBox rtb = (RichTextBox)obj; rtb.Document = (FlowDocument)args.NewValue; }}
I hope you find a use for this – I simply need it written down somewhere so I don't forget!
- Binding and styling text to a RichTextBox in WPF
- Delete text in a RichTextBox
- How to: Create a Binding in Code
- UpdateSourceTrigger Property in WPF Binding
- [WPF] Binding Enum to ComboBox
- WPF Binding ItemsSource to Enum
- How to place all WPF commands and related events centrally in a static class
- How can I get a FlowDocument Hyperlink to launch browser and go to URL in a WPF app?
- Binding to a dictionary in Silverlight with INotifyPropertyChanged
- How can I create a data binding in code using WPF?
- WPF richtextbox
- csharp: Data binding in WPF DataGrid control
- csharp: Data binding in WPF DataGrid control
- [WPF] Binding ContextMenu to its logical Parent
- How to Navigate, Group, Sort and Filter Data in WPF
- Drag and Drop Items in a WPF ListView
- Convert selected text to link (works in FF and IE)
- Adding shadows and glows to text in Texture2D.m
- TypeConverter使用
- SpringMVC的拦截器Interceptor
- xmlns:sys="clr-namespace:System;assembly=mscorlib" NOTE: System;与assembly中间不能有空格
- Spring笔记——Spring容器:ApplicationContext
- sql之left join、right join、inner join的区别
- Binding and styling text to a RichTextBox in WPF
- BeanWrapper 设置和获取属性值
- Struct 是值类型,不支持继承
- 日志记录、性能监控的三种实现方式
- delegate, event
- MSTest DeploymentItemAttribute
- 使用Fiddler拦截http请求
- http://forensics.idealtest.org CASIA图像篡改数据库
- 在WPF中应用弱事件模式