WPF: How to make RichTextBox look like TextBlock? WPF: How to make RichTextBox look like TextBlock? wpf wpf

WPF: How to make RichTextBox look like TextBlock?


I know this is annoying as hell.

RichTextBox sets this PagePadding in it's CreateRenderScope(), ie when it gets attached to the visual tree. At this time all properties are usually already set and thus the PagePadding gets reset.

What I'm about to show you is a more general form of how you can do this using an attached property. In my own code I do this usually more tightly because I know that a) the flowdocument does not change (not having to worry about registering the same handler twice) and b) the padding does not change (having the eventhandler just be ((FlowDocument)s).PagePadding = new Thickness(0.0);. For this being SO though I'll provide a general solution that you can just plug in.

The Solution:

        <RichTextBox BorderThickness="0" Margin="0" Padding="0">            <FlowDocument local:FlowDocumentPagePadding.PagePadding="0">                <Paragraph>                    <Run>text</Run>                </Paragraph>            </FlowDocument>        </RichTextBox>

public static class FlowDocumentPagePadding{    public static Thickness GetPagePadding(DependencyObject obj)    {        return (Thickness)obj.GetValue(PagePaddingProperty);    }    public static void SetPagePadding(DependencyObject obj, Thickness value)    {        obj.SetValue(PagePaddingProperty, value);    }    public static readonly DependencyProperty PagePaddingProperty =        DependencyProperty.RegisterAttached("PagePadding", typeof(Thickness), typeof(FlowDocumentPagePadding), new UIPropertyMetadata(new Thickness(double.NegativeInfinity),(o, args) =>            {                var fd = o as FlowDocument;                if (fd == null) return;                var dpd = DependencyPropertyDescriptor.FromProperty(FlowDocument.PagePaddingProperty, typeof(FlowDocument));                dpd.RemoveValueChanged(fd, PaddingChanged);                fd.PagePadding = (Thickness) args.NewValue;                dpd.AddValueChanged(fd, PaddingChanged);            }));    public static void PaddingChanged(object s, EventArgs e)    {        ((FlowDocument)s).PagePadding = GetPagePadding((DependencyObject)s);    }}

original sourcecode commentary:

In the original source of RichTextBox.CreateRenderScope() the developers included this comment:

// Set a margin so that the BiDi Or Italic caret has room to render at the edges of content.// Otherwise, anti-aliasing or italic causes the caret to be partially clipped.renderScope.Document.PagePadding = new Thickness(CaretElement.CaretPaddingWidth, 0, CaretElement.CaretPaddingWidth, 0);

bug report

here is the bug report on Microsoft Connect


The whole thing as I previously wrote doesn't work. For some reason the PagePadding is being overwritten as "5,0". However, when I used data-binding, it worked properly. So simply databind to a Thickness of 0. For it to work, you have to two-way databind:

<Window    x:Class="WpfApplication1.MainWindow"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    Title="MainWindow"    Height="350"    Width="525">    <StackPanel Orientation="Vertical">        <RichTextBox BorderThickness="0" Margin="0" Padding="0" >            <FlowDocument PagePadding="{Binding PagePadding, Mode=TwoWay}">                <Paragraph>LLL</Paragraph>            </FlowDocument>        </RichTextBox>        <TextBlock>LLL</TextBlock>    </StackPanel></Window>

Code behind:

namespace WpfApplication1{    using System.ComponentModel;    using System.Windows;    /// <summary>    /// Interaction logic for MainWindow.xaml    /// </summary>    public partial class MainWindow : INotifyPropertyChanged    {        public MainWindow()        {            InitializeComponent();            this.DataContext = this;        }        private Thickness pagePadding;        public Thickness PagePadding        {            get            {                return this.pagePadding;            }            set            {                this.pagePadding = value;                this.Changed("PagePadding");            }        }        private void Changed(string name)        {            var handlers = this.PropertyChanged;            if (handlers != null)            {                handlers.Invoke(this, new PropertyChangedEventArgs(name));            }        }        public event PropertyChangedEventHandler PropertyChanged;    }}


Try this. It works for me.... It's a lot less headache than the alternatives here...

<RichTextBox Padding="-5,0,-5,0">   <FlowDocument /></RichTextBox>