C# 将高WPF RichTextBox拆分为多个控件
我正在尝试获取RichTextBox的内容高度,如果它超过500px,请将其拆分为多个最大高度为500px的RichTextBox 有人知道怎么做吗?谢谢 编辑:C# 将高WPF RichTextBox拆分为多个控件,c#,.net,wpf,C#,.net,Wpf,我正在尝试获取RichTextBox的内容高度,如果它超过500px,请将其拆分为多个最大高度为500px的RichTextBox 有人知道怎么做吗?谢谢 编辑: “拆分”是指将超出高度限制的内容放入另一个RichTextBox中,解决方案不能仅仅因为项目的特殊性而更改当前RichTextBox的外观。您是否尝试在RichTextBox.ContentsResized事件中使用此代码 Private Sub rtb_ContentsResized(ByVal sender As Object,
“拆分”是指将超出高度限制的内容放入另一个RichTextBox中,解决方案不能仅仅因为项目的特殊性而更改当前RichTextBox的外观。您是否尝试在RichTextBox.ContentsResized事件中使用此代码
Private Sub rtb_ContentsResized(ByVal sender As Object, ByVal e As System.Windows.Forms.ContentsResizedEventArgs) Handles txtQuestion.ContentsResized
Dim h = e.NewRectangle.Height, w = e.NewRectangle.Width
h = Math.Max(h, sender.Font.Height)
h = Math.Min(h, Me.ClientSize.Height - 10 - sender.Top)
h += sender.Height - sender.ClientSize.Height + 1
sender.Height = h
端接头
如果有其他的c代码,我不知道
还有其他信息-richtextbox控件使用GDI绘制,而“Graphics.MeasureString”使用GDI+测量字符串。因此
“MeasureString”不会返回字符串的确切大小。恐怕你会的
必须深入研究GDI32-API才能获得准确的结果。如果您对使用Win32 GDI API调用感兴趣,我想我已经得到了您的答案。感谢google和stackoverflow WPF FlowDocument只能属于一个RichTextBox。但是如果您使用的是一个可以在UI中的不同点进行操作的文档,那么就不会有两个RichTextBox同时显示一个文档(而且不能,因为WPF会抱怨)。但是您使用的是单个文档还是多个文档?如果单身,读剩下的,如果没有,那么继续前进 使用MemoryStream和XamlReader/Writer在这里不起作用,因为我们希望保留一个文档,并在使用它的任何地方反映更改,所以每次都复制它是不可能的。 从stackoverflow的成员Jared处复制 WPF控件可以随意“取消插入”和“重新插入”,因此只需确保RichTextBox实例在整个向导中共享的上下文中可用,并确保在从一页移动到另一页时进行取消插入/重新插入即可。这还有一个好处,就是在向导中跨页面保存对编辑器状态的任何样式或更改(这可能是可取的) 如果无法跨页面共享RichTextBox实例,我认为有一种方法可以将文档与原始RichTextBox解除关联。看起来,为了解除文档与RichTextBox1的关联,您必须向RichTextBox1提供一个新文档。您不能将RichTextBox1.Document设置为null,但可以将RichTextBox1.Document设置为new FlowDocument(),我相信这会起作用 综上所述,多个RichTextBox控件不能直接共享FlowDocument。。 正如我上面所说,使用网格
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
我不知道这是否会分割控件,但我们可以在另一个RTB中看到文档(单个) 我在这个文本框问题上玩了一点,这并不容易^^ 我的想法是:
- 创建一个SplitRichTextBox自定义控件,该控件将继承RichTextBox(主要用于获取所有依赖属性)
- 添加一个MaxContentHeightdouble dependency属性来管理最大大小(在您的示例中为500px)
- 添加一个RemaindersIList
依赖项属性,该属性在拆分当前SplitRichTextBox后将作为其剩余部分 - 自定义SplitRichTextBox的ControlTemplate,以在面板中显示SplitRichTextBox内容和其他内容,以满足您的布局需要
- 重写SplitRichTextBox上的OnTextChanged方法
var flowDocument = this.Document;
flowDocument.MaxPageHeight = this.MaxContentHeight;
DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;
paginator.ComputePageCount();
由于paginator上的GetPage(inti)方法,现在您将能够检索每个页面的内容。第一页是第一个RichTextBox所需的内容。Remainders页将用于实例化Remainders依赖项属性
问题是这些页面不是直接的RTF或flowDocument。您需要以某种方式从paginator/page中提取数据,以了解如何拆分文档。这是我停下来的地方,也许不是我要走的路,但我认为值得一试
祝你好运 要获取另一个RichTextBox中超过高度限制的内容,我将使用以下方法:
private TextRange GetTopRange()
{
var result = textBox.GetPositionFromPoint(new Point(0, 0), true);
if (result == null)
return null;
result = result.GetInsertionPosition(LogicalDirection.Forward);
return new TextRange(result.DocumentStart, result);
}
private TextRange GetBottomRange()
{
var result = textBox.GetPositionFromPoint(new Point(textBox.ActualWidth, textBox.ActualHeight), true);
if (result == null)
return null;
result = result.GetInsertionPosition(LogicalDirection.Backward);
return new TextRange(result, result.DocumentEnd);
}
有了文本范围,您可以将它们复制到另一个RichTextBox的新FlowDocument中,截断它们(range.text=string.Empty
),等等
这是一种控制新月形网格大小以及随意创建rtb的简单方法
:D拆分表示特定的布局配置。您是否计划将它们放在特定的面板/项目控件上?这是仅用于显示还是需要拆分后端数据。您可以通过将相同的数据绑定到多个文本框并覆盖滚动来实现这一点position@BobVale您的解决方案听起来不错,唯一的问题是用户可以编辑RichTextBox内容,因此如果用户滚动内容,他们将看到隐藏的内容,有什么方法可以更改滚动条并删除所有不可见的文本?注释请点击Thx,但它仍然无法解释您的功能场景:)根据大小限制从一个文本框中取出两个文本框是可行的,但您必须知道如何处理第二个文本框。它会在一个面板中吗?项目控制?如果它是一个项控件,它是否会被数据绑定等。拆分文本框并将其插入到可视化树中的方式很重要。编辑:一个由多个文本框组成的面板组成的控件对你合适吗?@Sisyphe我将尝试解释这个场景,我们正在创建一个图书编辑器,当用户在当前页面中放置一个.doc文件时,我们将文件内容作为rtf,并放入一个RichTextBox中,但是如果内容高度超过页面高度,我们需要拆分内容创建一个新页面,并在新页面内插入另一个RichTextBox。一次只显示一页。我不能更改它
private TextRange GetTopRange()
{
var result = textBox.GetPositionFromPoint(new Point(0, 0), true);
if (result == null)
return null;
result = result.GetInsertionPosition(LogicalDirection.Forward);
return new TextRange(result.DocumentStart, result);
}
private TextRange GetBottomRange()
{
var result = textBox.GetPositionFromPoint(new Point(textBox.ActualWidth, textBox.ActualHeight), true);
if (result == null)
return null;
result = result.GetInsertionPosition(LogicalDirection.Backward);
return new TextRange(result, result.DocumentEnd);
}
public void CreateNewRtb(object sender, RoutedEventArgs routedEventArgs)
{
var res = (ResourceDictionary)Application.LoadComponent(new Uri("/Design/Style/TextAreaStyle.xaml", UriKind.Relative));
var mcRtb = new RichTextBox {Style = (Style) res["TextBoxStyle"], Name = "Folha" + J};
RegisterName("Folha" + J, mcRtb);
mcRtb.TextChanged += McRtbContentControl;
var gcrd = new RowDefinition();
var gcrdspace = new RowDefinition();
gcrd.Height = new GridLength(980);
GridControl.RowDefinitions.Add(gcrd);
Grid.SetColumn(mcRtb, 1);
Grid.SetRow(mcRtb, 1 + I);
GridControl.Children.Add(mcRtb);
I += 2;
J++;
gcrdspace.Height = new GridLength(30);
GridControl.RowDefinitions.Add(gcrdspace);
mcRtb.Focus();
}