简体   繁体   English

普通 TextBox 中的自动文本校正

[英]Automatic text correction in a normal TextBox

I want to implement an auto correction in some of the TextBox es in my application.我想在我的应用程序中的一些TextBox es 中实现自动更正。 What I mean by that is when user enters a text, after a few seconds, the text should be passed to method, get corrected and passed back to the text box.我的意思是当用户输入文本时,几秒钟后,文本应该传递给方法,得到更正并传递回文本框。

At the moment I have a very basic procedure for the correction.目前我有一个非常基本的更正程序。 My TextBoxes are supposed to get a measurement value from user (Such as 1.25 mA , 1.25uA , .666 A ).我的 TextBoxes 应该从用户那里获得一个测量值(例如1.25 mA1.25uA1.25uA .666 A )。

Imagine I have the correction method called CorrectValue :想象一下,我有一个名为CorrectValue的校正方法:

private void CorrectValue(TextBox tb)
{
   tb.Text = tb.Text.Trim().Remove('', string.Empty);
   //Actual correction is going to be much more complicated
}

So what would be the best approach fo doing so?那么这样做的最佳方法是什么? what kind of events should be rised?应该引发什么样的事件? how to count the seconds user spent writing in the TextBox?如何计算用户在 TextBox 中书写的秒数?

The best place for validating the input is the event Validating of the TextBox control.验证输入的最佳位置是 TextBox 控件的事件Validating If the entered value isn't valid, set e.Cancel in that event to false.如果输入的值无效,则将该事件中的e.Cancel设置为 false。

For me, the best event for such corrections / input validating is the Validating event.对我来说,这种更正/输入验证的最佳事件是Validating事件。

Problem with TextChanged is, it occurs while typing and you can't be sure the user has completed his input. TextChanged 的​​问题是,它在键入时发生,您无法确定用户已完成输入。

The most basic implementation would be for you to use the TextChanged event of the Textbox.最基本的实现是让您使用文本框的 TextChanged 事件。 In this event you can your method CorrectValue().在这种情况下,您可以使用您的方法 CorrectValue()。 As a parameter for the function you can cast the 'sender' parameter of the event to TextBox and pass it on to your method.作为函数的参数,您可以将事件的“sender”参数转换为 TextBox 并将其传递给您的方法。

Edit: For counting the time you could set a Timer and fire it every 0.5second for example.编辑:例如,为了计算时间,您可以设置一个 Timer 并每 0.5 秒触发一次。 After, let's say, 2 seconds you call the Correction method.比方说,2 秒后您调用 Correction 方法。 For example:例如:

private int _ticks;

private void textBox1_TextChanged(object sender, EventArgs e)
{
    timer1.Start();
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (_ticks++ == 4)
    {
        //Call correction method
        timer1.Stop();
        _ticks = 0;
    }
}

this is a silverlight user control i made (it's an extract from actual production code, works flawlessly) which does exactly what you need: react to input with a certain delay.这是我制作的Silverlight用户控件(它是从实际生产代码中提取的,可以完美运行),它完全符合您的需求:对输入做出一定的延迟。 it uses events to mimic "textchanged".它使用事件来模仿“textchanged”。 Adapting it to windows forms is straightforward.使其适应 Windows 窗体很简单。

public partial class DelayedTextBox : UserControl
{
    private DispatcherTimer eventTimer = new DispatcherTimer();
    public double TextChangedDelay
    {
        get { return eventTimer.Interval.TotalMilliseconds; }
        set { eventTimer.Interval = TimeSpan.FromMilliseconds(value); }
    }

    public delegate void DelayedTextChangedHandler(object sender, RoutedEventArgs e);
    public event DelayedTextChangedHandler DelayedTextChange;

    private object relayedSender = null;
    private RoutedEventArgs relayedE = null;

    public string Text
    {
        get
        {
            return PlainTextBox.Text;
        }

        set
        {
            PlainTextBox.Text = string.IsNullOrEmpty(value) ? string.Empty : value;
        }
    }

    //----------------------------------------------------------------------------------------------
    public TimedTextChangedTextBox()
    {
        InitializeComponent();

        TextChangedDelay = 500;
        eventTimer.Tick += new EventHandler(eventTimer_Tick);
    }

    private void StartTimer(object sender, RoutedEventArgs e)
    {
        relayedSender = sender;
        relayedE = e;
        eventTimer.Start();
    }

    private void StopTimer()
    {
        eventTimer.Stop();
        relayedSender = null;
        relayedSender = null;
    }

    private void eventTimer_Tick(object sender, EventArgs e)
    {
        StopTimer();
        if (DelayedTextChange != null)
            DelayedTextChange(relayedSender, relayedE);
    }

    private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (!maskedInput)
            ReactToInput(sender, e);
    }

    private void ReactToInput(object sender, RoutedEventArgs e)
    {
        if (!eventTimer.IsEnabled)
        {
            StartTimer(sender, e);
        }
        else
        {
            StopTimer();
            StartTimer(sender, e);
        }
    }
}

you can use the control the exact same way you normally use a TextBox.您可以使用与通常使用 TextBox 完全相同的方式来使用该控件。 subscribe to its DelayedTextChange event to react to user input.订阅其DelayedTextChange事件以响应用户输入。

This is obviously a really old post, but anyone looking for a simplified implementation may get some use out of the following:这显然是一篇很老的帖子,但是任何寻找简化实现的人都可以从以下内容中得到一些用处:

在此处输入图片说明

using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

private Dictionary<string, string> AutoCorrectDictionary => 
    File.ReadAllLines(@"C:\AutoCorrect.txt").ToDictionary(ln => ln.Split('|')[0], ln => ln.Split('|')[1]);

private void textBox1_TextChanged(object sender, EventArgs e)
{
    var cur = textBox1.SelectionStart;
    var match = new Regex(@"[^\s]+\s$").Match(textBox1.Text.Substring(0, cur)).Value;
    if (!AutoCorrectDictionary.ContainsKey(match.Trim().ToLower())) return;
    var replaceTxt = $@"{AutoCorrectDictionary[match.Trim().ToLower()]} ";
    textBox1.Text = textBox1.Text.Remove(cur - match.Length, match.Length)
        .Insert(cur - match.Length, replaceTxt);
    textBox1.SelectionStart = cur + (replaceTxt.Length - match.Length);
}

The dictionary I used for this example ("C:\\AutoCorrect.txt") includes 970 entries of key/value pairs separated by a '|', but you could use whatever you like.我在本示例中使用的字典 ("C:\\AutoCorrect.txt") 包含 970 个键/值对条目,以“|”分隔,但您可以使用任何您喜欢的条目。 In practice, I stick the AutoCorrectDictionary() in a static class that gets populated on startup.在实践中,我将AutoCorrectDictionary()放在一个在启动时填充的静态类中。 I did it the way I did here so that it would be clear what AutoCorrectDictionary() was.我按照我在这里的方式进行操作,以便清楚AutoCorrectDictionary()是什么。

Enjoy!享受!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM