Подтвердить что ты не робот

WPF: Как сделать RichTextBox похожим на TextBlock?

Как я могу сделать RichTextBox без полей, границ, пропусков и т.д.? Другими словами, чтобы отображать контент так же, как TextBlock, это так? Я пробовал это:

<RichTextBox Margin="0" Padding="0" Grid.Row="0" BorderThickness="0" >
    <FlowDocument >
        <Paragraph>LLL</Paragraph>
    </FlowDocument>
</RichTextBox>
<TextBlock>LLL</TextBlock>

Но результат получается по-прежнему не так, как я хочу:

enter image description here

По-прежнему есть некоторое пространство перед содержимым документа (а также, возможно, после, сверху или снизу документа...). Как его удалить?


Если вам интересно, зачем мне это нужно: я пытаюсь сделать H.B. ответ на мой вопрос Создать редактор гитарных аккордов в WPF для работы с kerning, и я не хочу иметь неестественное пространство между персонажами.


Изменить

Таким образом, это не ControlTemplate по крайней мере не только потому, что следующий код даст точно такой же результат (как тот, что изображен на картинке выше):

<RichTextBox Margin="0" Padding="0" Grid.Row="0" BorderThickness="0">
    <RichTextBox.Template>
        <ControlTemplate>
            <ScrollViewer Padding="0" Margin="0" x:Name="PART_ContentHost"/>
        </ControlTemplate>
    </RichTextBox.Template>
    <FlowDocument PagePadding="0">
        <Paragraph Padding="0" Margin="0" >LLL</Paragraph>
    </FlowDocument>
</RichTextBox>

И я думал, что будет легко ответить на вопрос... Интересное наблюдение:, когда у меня установлен шаблон, и я установил PagePadding="0" на FlowDocument , он отображает макет, который я хочу в дизайнере VisualStudio - , пока я не запустил демонстрацию. В демо снова не так... И когда я закрываю демо, он снова ошибается в дизайнере. Это небольшая ошибка VS или она на самом деле настроена на правильную компоновку на некоторое время, но затем что-то изменяет значение PagePadding на некорректное значение?


Edit # 2

Даниэль Роуз отредактировал ответ, также не работает для меня. Это XAML:

<FlowDocument PagePadding="{Binding PagePadding}">
    <Paragraph x:Name="paragraph" Padding="0" 
        TextIndent="0"  Margin="0,0,0,0" >hello</Paragraph>
</FlowDocument>

И это в коде:

public static DependencyProperty PagePaddingProperty =
            DependencyProperty.Register("PagePadding", typeof(Thickness),   typeof(EditableTextBlock),
            new PropertyMetadata(new Thickness(0)));

public Thickness PagePadding {
    get { return (Thickness)GetValue(PagePaddingProperty); }
    set { SetValue(PagePaddingProperty, value); }
}

Без изменений результата. Осталось место.


Edit # 3

После добавления двусторонней привязки, поскольку Даниэль Роуз предложил в своем редакторе las, он работает. Тем не менее, я действительно не думаю, что это очень ясно (иметь свойство зависимости, потому что мне нужно поддерживать PagePadding при значении 0). Я думаю, что это обходное решение. Если у кого-то есть лучшее решение, поделитесь им.

Очевидно, что "изменение PagePadding" от FlowDocument до 0,5 является ошибкой. Если у кого-то есть учетная запись MSDN, было бы неплохо, если бы они сообщили об этой ошибке.

4b9b3361

Ответ 1

Я знаю, что это раздражает как ад.

RichTextBox устанавливает этот PagePadding в нем CreateRenderScope(), то есть когда он привязывается к визуальному дереву. В это время все свойства обычно уже установлены, и, таким образом, страницаPadding получает reset.

То, что я собираюсь показать вам, - это более общая форма того, как вы можете это сделать, используя прикрепленное свойство. В моем собственном коде я делаю это обычно более жестко, потому что я знаю, что a) flowdocument не изменяется (не нужно беспокоиться о регистрации одного и того же обработчика дважды) и b) заполнение не изменяется (наличие обработчика событий просто ((FlowDocument)s).PagePadding = new Thickness(0.0);.Если это SO, хотя я предоставлю общее решение, которое вы можете просто подключить.

Решение:

        <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);
    }
}

исходный код исходного кода:

В исходном источнике RichTextBox.CreateRenderScope() разработчики включили этот комментарий:

// 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);

отчет об ошибке

вот отчет об ошибке в Microsoft Connect

Ответ 2

Все, что я написал ранее, не работает. По какой-то причине PagePadding перезаписывается как "5,0". Однако, когда я использовал привязку данных, он работал правильно. Так просто databind до толщины 0. Для этого вы должны иметь двустороннюю привязку:

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

Код позади:

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;
    }
}

Ответ 3

Попробуйте это. Это работает для меня... Это гораздо меньше головной боли, чем альтернативы здесь...

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