在WPF中展示RichTextBox的行号

10

你有考虑过这个 SO问题中提到的任何选项吗?Aqistar不再是可供选择的替代方案(链接已失效),但AvalonEdit可能是一个可行的备选方案。 - Anders Gustafsson
你想要使用MVVM模式还是不使用? - fhnaseer
你可能需要创建自己的自定义文本框和其他组件来实现这一点。 - fhnaseer
@Faisal Hafeez 不使用 MVVM。 - Karl_Schuhmann
5个回答

10

我认为只需添加一个简单的解决方案...

Avalon下载)已被提到,以下是使用它进行行线的方法:

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

如果您想要实现自己的定制化语法高亮(Avalon编辑器可高度扩展-详情请见该CodeProject文章),您需要定义自己的IHighlightingDefinition,然后从代码中将其注册到HighlightingManager中,并添加一些补充内容。但这是一个独立的长篇故事。


Avalon Edit使用FlowDocument还是TextBlock?你能告诉我在哪里可以找到LineNumbers函数吗?你能给我展示一个测试应用程序,其中使用了Avalon的LineNumbers函数吗? - Karl_Schuhmann
Karl,上面是测试应用程序 - 我使用并检查了它,它可以正常工作。它有自己的 TextView 和自己的系统(与 RichTextBox 无关)。你需要熟悉它的内部工作方式(它是第三方控件),否则它可以很好地完成你所需的所有工作。 - NSGaga-mostly-inactive
我已经在我的软件中测试过了。当我只有语法名称作为字符串时,你能告诉我如何使用C#代码更改SyntaxHighlighting吗? - Karl_Schuhmann
我进行了编辑 - 你也可以有自己的语法等等,但正如我所说,这超出了本文的范围。我希望你对这个答案感到满意 :)。如果你需要更多的帮助,我建议你开一个新问题,我很乐意帮助你,只要提出更小、更具针对性的问题即可。干杯。 - NSGaga-mostly-inactive
真的很棒的编辑器。虽然我正在努力学习它,但它肯定是一个很好的选择,甚至是最终选择。谢谢。 - cheny

7

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

获取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 上显示行号。 - Felice Pollano
谢谢您的回答。它有效,但我无法使用您的解决方案,因为我必须在richTextBox中加载带有格式文本的FlowDocument。 - Karl_Schuhmann
希望Downvoter看到了@Karl_Schuhmann的评论,说它可以工作。 - Chamika Sandamal
1
将监听器更改为 textBox.TextChanged += new TextChangedEventHandler(box_SizeChanged); - roady

2

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

一旦您已经安装了该组件并将其添加到您的表单中,您可以通过转到控件的属性并设置Margins>Margin0>Width来显示行号。您也可以通过编程方式设置这个属性:

scintilla1.Margins.Margin0.Width = 20;

如果您计划采取这种方法,您可能会发现ScintillaNet文档很有用——当我开始时,我发现它真的很有帮助。

你能给我展示一个例子吗?我在那里找不到 LineNumber 函数。 - Karl_Schuhmann
@Karl 我的错,确保你也按照“配置搜索路径”的步骤进行操作。整个页面都非常重要,尤其是这两个部分。我会更新我的回答以便更清楚地说明。 - Ben Catterall
我找到了它们,但我无法使用它们。在这里:链接 #编辑:我使用.NET Framework 4.0 - Karl_Schuhmann
@Karl 啊,我也遇到过那个问题 - 确保你在表单设计器中使用它。 (.NET 4 也应该没问题) - Ben Catterall
2
我知道为什么它不工作,因为我使用的是WPF而不是WinForms。 - Karl_Schuhmann
显示剩余4条评论

1

您可以在AvalonEdit中找到最好的例子。除了行号之外,还有很多内容,但您可以研究它是如何完成的,代码非常清晰。这篇CodeProject文章是一个开始了解我们正在谈论的内容的起点。


我知道AvalonEdit,但我必须在我的richtextbox中加载格式化文本。我不能使用高亮显示。你能给我展示一个例子吗?@FelicePollano - Karl_Schuhmann

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接