【问题标题】:Show LineNumbers from the RichTextBox in WPF在 WPF 中显示 RichTextBox 中的 LineNumbers
【发布时间】:2013-03-14 16:56:42
【问题描述】:

我找到了一个示例,如何在 Windows 窗体中显示来自 RichTextBox 的 LineNumbers。 http://www.codeproject.com/Articles/38858/Line-Numbers-for-RichText-Control-in-C

有人在 WPF 中有一个例子吗?

编辑:

有人使用 AvalonEdit,因为他想在他的程序中显示 LineNumbers 并且可以通过我的问题帮助我。

【问题讨论】:

  • 您是否考虑过this SO 问题中提到的任何选项? Aqistar 似乎不再是替代品(链接已失效),但AvalonEdit 可能是一个可行的替代品?
  • 您想为此关注 MVVM 还是不关注 MVVM?,
  • 您可能需要制作自己的自定义文本框和其他东西才能实现这一目标。
  • @Faisal Hafeez 没有 MVVM。

标签: c# wpf richtextbox line-numbers


【解决方案1】:

只需为您的文本框使用自定义模板;以下答案可能对您有所帮助:

Visible line count of a TextBlock

更新


更改答案以按 OP 预期工作。

<Style x:Key="Local_TextBox" TargetType="{x:Type TextBoxBase}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBoxBase}">
                <Border Name="Border" Background="{TemplateBinding Background}">
                    <ScrollViewer x:Name="PART_ContentHost" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

设计师,

<DockPanel>
    <TextBlock Text="{Binding ElementName=uiTextBox, Path=(local:AttachedProperties.BindableLineCount)}"/>
    <TextBox x:Name="uiTextBox" TextWrapping="Wrap" local:AttachedProperties.HasBindableLineCount="True"
            AcceptsReturn="True" Text="{Binding LongText}" Style="{StaticResource Local_TextBox}" />
</DockPanel>

附加属性,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace Cmsn.Software.Tutorials.numberedTextBox
{
    public class AttachedProperties
    {
        #region BindableLineCount AttachedProperty
        public static string GetBindableLineCount(DependencyObject obj)
        {
            return (string)obj.GetValue(BindableLineCountProperty);
        }

        public static void SetBindableLineCount(DependencyObject obj, string value)
        {
            obj.SetValue(BindableLineCountProperty, value);
        }

        // Using a DependencyProperty as the backing store for BindableLineCount.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BindableLineCountProperty =
            DependencyProperty.RegisterAttached(
            "BindableLineCount",
            typeof(string),
            typeof(AttachedProperties),
            new UIPropertyMetadata("1"));

        #endregion // BindableLineCount AttachedProperty

        #region HasBindableLineCount AttachedProperty
        public static bool GetHasBindableLineCount(DependencyObject obj)
        {
            return (bool)obj.GetValue(HasBindableLineCountProperty);
        }

        public static void SetHasBindableLineCount(DependencyObject obj, bool value)
        {
            obj.SetValue(HasBindableLineCountProperty, value);
        }

        // Using a DependencyProperty as the backing store for HasBindableLineCount.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HasBindableLineCountProperty =
            DependencyProperty.RegisterAttached(
            "HasBindableLineCount",
            typeof(bool),
            typeof(AttachedProperties),
            new UIPropertyMetadata(
                false,
                new PropertyChangedCallback(OnHasBindableLineCountChanged)));

        private static void OnHasBindableLineCountChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var textBox = (TextBox)o;
            if ((e.NewValue as bool?) == true)
            {
                textBox.SizeChanged += new SizeChangedEventHandler(box_SizeChanged);
                textBox.SetValue(BindableLineCountProperty, textBox.LineCount.ToString());
            }
            else
            {
                textBox.SizeChanged -= new SizeChangedEventHandler(box_SizeChanged);
            }
        }

        static void box_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var textBox = (TextBox)sender;
            string x = string.Empty;
            for (int i = 0; i < textBox.LineCount; i++)
            {
                x += i + 1 + "\n";
            }
            textBox.SetValue(BindableLineCountProperty, x);
        }
        #endregion // HasBindableLineCount AttachedProperty
    }
}

【讨论】:

  • -1 因为 OP 不仅要计算行数,还要在 RichEdit 上显示行号。
  • 感谢您的回答。它有效,但我不能使用你的解决方案,因为我必须在 RichTextBox 中加载带有格式化文本的 FlowDocument
  • Hope Downvoter 看到 @Karl_Schuhmann 的评论说它有效。
  • 将监听器改为textBox.TextChanged += new TextChangedEventHandler(box_SizeChanged);
【解决方案2】:

最好的example you can find is in AvalonEdit。反正除了行号还有很多,但是你可以研究一下它是怎么做的,代码很清楚。 this CodeProject article

【讨论】:

  • 我知道 AvalonEdit,但我必须在我的 Richtextbox 中加载格式化文本。我不能使用突出显示。你能给我举个例子吗? @FelicePollano
【解决方案3】:

ScintillaNET 是一个值得尝试的好组件。它是 .NET 版本的 Scintilla,它是 Notepad++ 编辑器(以及其他)中的关键组件。我不知道它与 AvalonEdit 相比如何,但我发现在我的代码中实现它相当容易,并且它具有您需要的功能(以及更多功能)。

一旦您将installed the component 添加到表单中,您就可以通过转到控件的属性并设置Margins>Margin0>Width 来show line numbers。您也可以通过编程方式进行设置:

scintilla1.Margins.Margin0.Width = 20;

如果您打算走这条路,您可能会发现 ScintillaNet documentation 很有用 - 我刚开始时发现它真的很有帮助。

【讨论】:

  • 你能给我举个例子吗?我在那里找不到 LineNumber 函数。
  • 我在上面添加了更多关于行号和一些文档链接的详细信息。希望对您有所帮助!
  • 我按照步骤操作,但我的toolbox中没有出现控件
  • @Karl 我的错,请确保您也按照配置搜索路径的步骤进行操作。整个页面非常重要,尤其是那两个部分。为了清楚起见,我会更新我的答案。
  • 我知道为什么它不起作用,因为我使用的是 WPF,而不是 WinForms
【解决方案4】:

我想只是添加一个简单的解决方案...

Avalon (Download) 已经提到,这里是如何用它来做行:

<avalon:TextEditor ShowLineNumbers="True" Width="500" Height="500"
                    Text="some more test&#10; some more test&#10; some more test&#10; some more test&#10; some more test&#10; some more test&#10; some more test&#10; some more test&#10; some more test&#10; ">
</avalon:TextEditor>  

这是一个非常强大的编辑器——我已经在它和生产环境中做了很多工作(自定义语言编译器等)。它是免费的,所以它有它的“怪癖”,但它允许你做几乎任何你需要的事情。我不确定你在说哪种格式的文本 - 但你需要的任何事情都可以完成,并且不需要太多的代码行,如果你知道如何,在哪里注入(你可以添加自己的生成器,转换器,几乎任何视觉效果,代码完成等 - 我对它没有既得利益:)

编辑

语法高亮小示例:

<avalon:TextEditor 
  ShowLineNumbers="True" 
  SyntaxHighlighting="C#" Width="500" Height="500"
  Text="void Test(int id, string name)&#10;{&#10;&#09;name = name + id.ToString();}" />  

据我所知,支持"XmlDoc", "C#", "JavaScript", "HTML", "ASP/XHTML", "Boo", "Coco", "CSS", "C+", "Java", "Patch", "PHP", "TeX", "VBNET", "XML"

如果您想实现自己的自定义syntax highlighting(Avalon 编辑器是高度可扩展的 - 有关详细信息,请参阅 code project article mentioned)...

您需要定义自己的IHighlightingDefinition,然后使用代码中的HighlightingManager 进行注册 - 然后添加更多内容来补充。但这本身就是一个漫长的故事。

【讨论】:

  • Avalon Edit 是否使用 FlowDocument 或 TextBlock,您能告诉我在哪里可以找到 LineNumbers 的函数吗?你能告诉我一个使用 Avalon 的 LineNumbers 函数的测试应用程序吗
  • Karl,上面是测试应用程序 - 我使用它并检查了它,它“按原样”工作。它有自己的TextView 和自己的系统(与 RichTextBox 无关)。你需要习惯它的内部运作(它是第 3 方控制),否则工作正常,你可以做你需要的一切。
  • 我已经在我的软件中测试过了。当我只有语法的名称作为字符串时,你能告诉我如何使用 C#-Code 更改 SyntaxHighlighting 吗?
  • 我编辑过——你也可以有自己的语法等等——但正如我所说的,这超出了这个范围。我希望你会对这个答案感到满意:)。如果您需要更多,我建议您提出一个新问题,我很乐意为您提供帮助,只需提出较小的、有针对性的问题。干杯。
【解决方案5】:

这是一个很好的CodeProject article,它显示了在 TextBox 控件中实现行号和一些其他不错的代码编辑功能的详细方法。如果您不关心它是如何构建的,只需下载示例文件并使用包含已编译控件的包含 dll。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    相关资源
    最近更新 更多