[英]WPF: How to make RichTextBox look like TextBlock?
如何制作没有边距、边框、填充等的RichTextBox
? 换句话说,以与TextBlock
相同的方式显示内容吗? 我试过这个:
<RichTextBox Margin="0" Padding="0" Grid.Row="0" BorderThickness="0" >
<FlowDocument >
<Paragraph>LLL</Paragraph>
</FlowDocument>
</RichTextBox>
<TextBlock>LLL</TextBlock>
但产生的结果仍然不是我想要的:
文档内容之前仍有一些空间(也可能在文档顶部或底部之后......)。 我怎样才能删除它?
如果您对我为什么需要这个感兴趣:我试图让HB 回答我的问题在 WPF 中创建吉他和弦编辑器以使用字距调整,我不想在字符之间有不自然的空间。
所以它不是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>
而且我认为这将是一个容易回答的问题......有趣的观察:当我设置模板并在FlowDocument
上设置PagePadding="0"
时,它会在 VisualStudio 设计器中显示我想要的布局-直到我运行 demo 。 在演示中又错了……当我关闭演示时,设计器又错了。 这是 VS 的一个小错误,还是它实际上设置了一段时间的正确布局,但随后某些东西将PagePadding
的值更改回了某个错误的值?
丹尼尔罗斯编辑的答案也不适合我。 这是 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); }
}
结果没有变化。 空间依然存在。
按照 Daniel Rose 在他的 las 编辑中建议的那样添加双向绑定后,它就可以工作了。 我仍然认为它不是很清楚(具有依赖属性,因为我需要将PagePadding
保持在 0 值)。 我认为这是一个 hack - bug 解决方法。 如果有人有更好的解决方案,请分享。
显然,将FlowDocument
的PagePadding
更改为0,5
是一个错误。 如果有人有 MSDN 帐户,如果他们报告此错误会很好。
我知道这很烦人。
RichTextBox
将此 PagePadding 设置在它的CreateRenderScope()
中,即当它附加到可视树时。 此时,所有属性通常都已设置,因此 PagePadding 会被重置。
我将要向您展示的是一种更通用的形式,说明如何使用附加属性来做到这一点。 在我自己的代码中,我通常会更严格地执行此操作,因为我知道 a)流文档不会改变(不必担心注册相同的处理程序两次)和 b)填充不会改变(事件处理程序只是((FlowDocument)s).PagePadding = new Thickness(0.0);
。为此,尽管我将提供一个您可以插入的通用解决方案。
<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);
我之前写的整个事情都不起作用。 由于某种原因,PagePadding 被覆盖为“5,0”。 但是,当我使用数据绑定时,它可以正常工作。 所以只需将数据绑定到 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;
}
}
尝试这个。 它对我有用......它比这里的替代品要少得多......
<RichTextBox Padding="-5,0,-5,0">
<FlowDocument />
</RichTextBox>
其实这不是bug。 此行为旨在改进显示BiDi和斜体插入符号指示器。
查看 .Net 4.8 源码,在RichTextBox.cs文件中:
// Allocates the initial render scope for this control.
internal override FrameworkElement CreateRenderScope()
{
FlowDocumentView renderScope = new FlowDocumentView();
renderScope.Document = this.Document;
// 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);
// We want current style to ignore all properties from theme style for renderScope.
renderScope.OverridesDefaultStyle = true;
return renderScope;
}
以及CaretElement.cs文件中的CaretElement.CaretPaddingWidth
定义:
// Caret padding width to ensure the visible caret for Bidi and Italic.
// Control(TextBox/RichTextBox) must have the enough padding to display
// BiDi and Italic caret indicator.
internal const double CaretPaddingWidth = 5.0;
为了更有效,让我们看看以下三个控件, TextBlock
, TextBox
和RichTextBox
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock FontStyle="Italic" FontSize="48">LLL in TextBlock</TextBlock>
<TextBox Grid.Row="1" FontStyle="Italic" FontSize="48" BorderThickness="0">LLL in TextBox</TextBox>
<RichTextBox Grid.Row="2" FontStyle="Italic" FontSize="48" BorderThickness="0" Height="Auto" >
<FlowDocument PagePadding="0" >
<Paragraph TextIndent="0">LLL in RichTextBox</Paragraph>
</FlowDocument>
</RichTextBox>
</Grid>
这些控件在使用相同的字体大小/样式时,填充和边距显示如下:
很容易看到TextBox
还具有一些额外的间距,旨在通过显示插入符号指示符。 但是由于在RichTextBox
中插入符号具有更多的视觉效果,因此为它保留了更多的空间。
对我有用的解决方案只是设置<RichTextBox Padding="-5,0,0,0">
,就像史蒂夫在帖子中提出的那样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.