使用长行标记增强WPF TextBox?

时间:2012-05-12 16:04:03

标签: c# wpf xaml

我在WPF中有一个TextBox,如下所示:

<TextBox Height="48" />

没什么特别的,看起来像这样:

enter image description here

现在我需要做的是拥有清晰漂亮的长线标记:

enter image description here

所以基本上我想在位置50处画一个线标记。我将使用固定宽度的字体使我自己更容易,所以我可以轻松地计算位置。

现在问题是,我不想限制它的输入,但是当你达到50个字符的限制时,我希望它能给出一个视觉胶水。

为了使问题更难,我需要对以下行/行(72个字符)的此限制更高,如下所示:

enter image description here

共享相同位置的行标记(行2-n)可以是单行而不是多行。

我也对其他建议持开放态度,但只要它提供一种干净的方式告诉用户他即将超出限制,我就很酷。

注意:我不希望任何文字说“你还剩x个字符”或其他东西。空间有限,我希望它是可视的。

更新:我真的很感激是否可以添加工具提示,以便在悬停标记时向用户说明其目的。

1 个答案:

答案 0 :(得分:3)

由于你想要在视觉上装饰文本框,所以我想到的第一件事就是恰当地命名为Adnorner

我写了一个快速演示,展示了如何装饰文本框。线条绘制部分很简单,棘手的部分是找出应该绘制线条的位置。我在我的例子中硬编码了行位置。我想你必须做一些文本测量来找出你的文本有多高(对于行高)和50个字符值多长(以抵消你的行)。

enter image description here

这是xaml:

<Window x:Class="WpfApplication4.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">
    <Grid  HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" >
        <AdornerDecorator>
            <TextBox TextWrapping="Wrap"  AcceptsReturn="True" x:Name="myTextBox" Width="200px" Height="200px">hello</TextBox>
        </AdornerDecorator>
    </Grid>
</Window>

背后的代码

using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace WpfApplication4
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
            myAdornerLayer.Add(new LineAdorner(myTextBox));
        }

        // Adorners must subclass the abstract base class Adorner.

        #region Nested type: LineAdorner

        public class LineAdorner : Adorner
        {
            // Be sure to call the base class constructor.
            public LineAdorner(UIElement adornedElement)
                : base(adornedElement)
            {
            }

            // A common way to implement an adorner's rendering behavior is to override the OnRender
            // method, which is called by the layout system as part of a rendering pass.
            protected override void OnRender(DrawingContext drawingContext)
            {
                var adornedElementRect = new Rect(AdornedElement.DesiredSize);

                var renderPen = new Pen(new SolidColorBrush(Colors.Red), 1.5);

                // Draw lines.
                drawingContext.DrawLine(renderPen,
                                        new Point(adornedElementRect.TopLeft.X + 75, adornedElementRect.TopLeft.Y),
                                        new Point(adornedElementRect.TopLeft.X + 75, adornedElementRect.TopLeft.Y + 20));
                drawingContext.DrawLine(renderPen,
                                        new Point(adornedElementRect.TopLeft.X + 120, adornedElementRect.TopLeft.Y + 20),
                                        new Point(adornedElementRect.TopLeft.X + 120, adornedElementRect.TopLeft.Y + 40));
                drawingContext.DrawLine(renderPen,
                                        new Point(adornedElementRect.TopLeft.X + 120, adornedElementRect.TopLeft.Y + 40),
                                        new Point(adornedElementRect.TopLeft.X + 120, adornedElementRect.TopLeft.Y + 60));
            }
        }

        #endregion
    }
}