4

我正在尝试获取 RichTextBox 的内容高度,如果它超过 500px,则将其拆分为多个最大高度为 500px 的 RichTextBox。

有人知道怎么做吗?谢谢。

编辑:

“拆分”是指将超出高度限制的内容放在另一个 RichTextBox 中,由于项目的特殊性,该解决方案不能仅仅改变当前 RichTextBox 的外观。

4

5 回答 5

3

我在这个拆分 RichTextBox 问题上玩了一点,这并不容易 ^^ 我的想法是这样的:

  • 创建一个将继承RichTextBox的SplitRichTextBox CustomControl (主要是获取所有依赖属性)
  • 添加MaxContentHeight双依赖属性来管理最大尺寸(在您的情况下为 500px)
  • 添加一个Remainders IList< RichTextBox > 依赖属性,一旦它被拆分,它将成为当前 SplitRichTextBox 的剩余部分。
  • 自定义 SplitRichTextBox 的 ControlTemplate 以在面板中显示 SplitRichTextBox 内容和其余内容,以满足您的布局需求。
  • 覆盖 SplitRichTextBox 上的 OnTextChanged 方法。

在此方法中检索底层的richTextBox flowDocument 并检索分页器。设置 MaxPageHeight 并计算文档页面。

var flowDocument = this.Document;
flowDocument.MaxPageHeight = this.MaxContentHeight;
DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;
paginator.ComputePageCount();

由于分页器上的 GetPage(int i) 方法,您现在可以检索每个页面的内容。第一页是您想要的第一个 RichTextBox。剩余页面将用于实例化 Remainders 依赖属性。

问题是页面不是直接的 RTF 或 flowDocument。您将需要以某种方式从分页器/页面中提取数据以了解如何拆分文档。这是我停下来的地方,也许不是要走的路,但我认为值得一试。

祝你好运 !

于 2012-11-08T08:58:46.833 回答
1

您是否尝试在 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 调用感兴趣,请看这里

于 2012-11-06T10:09:24.847 回答
1

我想我得到了你的答案。感谢 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(),我相信这会起作用。

从上面看,FlowDocument 不能被几个 RichTextBox 控件直接共享。所以正如我上面评论的那样,使用网格

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

包装 RTB 并在代码中使用

    FlowDocument doc = RTB1.Document;
    RTB1.Document = new FlowDocument();
    RTB2.Document = doc;

我不知道这是否会拆分控件,但我们可以在另一个 RTB 中看到文档(单个)。

于 2012-11-08T07:17:13.727 回答
1

要在另一个 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) 等。

于 2012-11-08T09:21:18.290 回答
-1
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();
}

这是控制新月网格大小和随意创建 rtb 的简单方法:D

于 2013-01-22T20:54:53.487 回答