C # attendre que l'utilisateur ait fini de taper dans une zone de texte

y a-t-il un moyen en C# d'attendre que l'utilisateur ait fini de taper dans une boîte de texte avant de saisir les valeurs qu'il a tapées sans frapper enter?

Révisé cette question un peu:

Ok j'ai une calculatrice simple qui multiplie par 2.

voici ce que je veux qu'il fasse: l'utilisateur entre une valeur comme 1000 dans une boîte de texte et il affiche automatiquement 2000.

Voici ce qui se passe: dès Que l'utilisateur entre de 1, multiplie par 2 et sorties 2.

22
demandé sur user990951 2011-11-04 00:29:32

12 réponses

Vous pouvez utiliser textbox onChange() événement. Si le texte est modifié dans la zone de texte, Cochez si la valeur saisie est un nombre et calculez la valeur totale en fonction de l'autre valeur.

3
répondu evilone 2011-11-03 20:36:16

je définis "fini de taper" maintenant comme "l'Utilisateur a tapé quelque chose mais n'a pas tapé rien après un certain temps". Ayant cela comme définition j'ai écrit une petite classe qui dérive de TextBox pour l'étendre par un DelayedTextChanged événement. Je ne m'assure pas que ce soit complet et sans bug, mais il a satisfait à un petit test de fumée. N'hésitez pas à modifier et/ou de l'utiliser. Je l'ai appelé MyTextBox parce que je ne pourrais pas trouver un meilleur nom maintenant. Vous pouvez utiliser le DelayedTextChangedTimeout propriété pour modifier le délai d'attente. Par défaut est 10000ms (=10 Secondes).

public class MyTextBox : TextBox
{
    private Timer m_delayedTextChangedTimer;

    public event EventHandler DelayedTextChanged;

    public MyTextBox() : base() 
    {
        this.DelayedTextChangedTimeout = 10 * 1000; // 10 seconds
    }

    protected override void Dispose(bool disposing)
    {
        if (m_delayedTextChangedTimer != null)
        {
            m_delayedTextChangedTimer.Stop();
            if (disposing)
                m_delayedTextChangedTimer.Dispose();
        }

        base.Dispose(disposing);            
    }

    public int DelayedTextChangedTimeout { get; set; }

    protected virtual void OnDelayedTextChanged(EventArgs e)
    {
        if (this.DelayedTextChanged != null)
            this.DelayedTextChanged(this, e);
    }

    protected override void OnTextChanged(EventArgs e)
    {
        this.InitializeDelayedTextChangedEvent();
        base.OnTextChanged(e);            
    }                

    private void InitializeDelayedTextChangedEvent()
    {
        if (m_delayedTextChangedTimer != null)
            m_delayedTextChangedTimer.Stop();

        if (m_delayedTextChangedTimer == null || m_delayedTextChangedTimer.Interval != this.DelayedTextChangedTimeout)
        {                
            m_delayedTextChangedTimer = new Timer();
            m_delayedTextChangedTimer.Tick += new EventHandler(HandleDelayedTextChangedTimerTick);
            m_delayedTextChangedTimer.Interval = this.DelayedTextChangedTimeout;
        }

        m_delayedTextChangedTimer.Start();
    }

    private void HandleDelayedTextChangedTimerTick(object sender, EventArgs e)
    {
        Timer timer = sender as Timer;
        timer.Stop();

        this.OnDelayedTextChanged(EventArgs.Empty);
    }
}
41
répondu esskar 2011-11-03 21:05:33

une autre solution simple serait d'ajouter une minuterie à votre formulaire, de définir la propriété intervalle à 250 puis d'utiliser l'événement tick de la minuterie comme suit:

private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Stop();
    Calculate(); // method to calculate value
}

private void txtNumber_TextChanged(object sender, EventArgs e)
{
    timer1.Stop();
    timer1.Start();
}
11
répondu RooiWillie 2015-02-05 14:23:23

si vous utilisez WPF et .NET 4.5 ou une version ultérieure, il y a une nouvelle propriété sur la partie liant d'un contrôle nommé "Delay". Il définit un intervalle de temps après lequel la source est mise à jour.

<TextBox Text="{Binding Name, Delay=500}" />

cela signifie que la source n'est mise à jour qu'après 500 millisecondes. Pour autant que je le vois, il fait la mise à jour après avoir tapé dans la boîte de texte terminé. Btw. cette propriété peut être utile dans d'autres situations, par exemple. ListBox etc.

7
répondu okieh 2016-02-06 07:55:00

vous pouvez gérer L'événement LostFocus de la zone de texte qui s'allume chaque fois que l'Utilisateur termine de taper et navigue loin de la zone de texte. Voici la documentation sur LostFocus: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx

cependant, je ne suis pas sûr de ce que vous essayez de faire exactement ici car la question n'est pas très claire sur ce que "finir" signifie.

4
répondu Michael Kingsmill 2011-11-03 20:31:49

j'ai fait face au même défi, et voici mon approche simple. Cela fonctionne sans problèmes.

public partial class Form2 : Form
    {
        static int VALIDATION_DELAY = 1500;
        System.Threading.Timer timer = null;
        public Form2()
        {
            InitializeComponent();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            TextBox origin = sender as TextBox;
            if (!origin.ContainsFocus)
                return;

            DisposeTimer();
            timer = new System.Threading.Timer(TimerElapsed, null, VALIDATION_DELAY, VALIDATION_DELAY);

        }
        private void TimerElapsed(Object obj)
        {
            CheckSyntaxAndReport();
            DisposeTimer();            
        }

        private void DisposeTimer()
        {
            if (timer != null)
            {
                timer.Dispose();
                timer = null;
            }
        }

        private void CheckSyntaxAndReport()
        {            
            this.Invoke(new Action(() => 
            {
                string s = textBox1.Text.ToUpper(); //Do everything on the UI thread itself
                label1.Text = s; 
            }
                ));            
        }
    }
3
répondu Sunil Purushothaman 2016-02-09 10:48:05

dans UWP, j'ai fait une vérification retardée en faisant une dernière heure statique de typographie et en vérifiant l'heure à laquelle l'événement "TextChanged" s'est produit. Cela attend jusqu'à ce que le dernier temps statique de typographie corresponde lorsqu'un nouveau temps "TextChanged" correspond et exécute ensuite la fonction désirée.

    private const int millisecondsToWait = 500;
    private static DateTime s_lastTimeOfTyping;
    private void SearchField_OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var latestTimeOfTyping = DateTime.Now;
        var text = ((TextBox)sender).Text;
        Task.Run(()=>DelayedCheck(latestTimeOfTyping, text));
        s_lastTimeOfTyping = latestTimeOfTyping;
    }

    private async Task DelayedCheck(DateTime latestTimeOfTyping, string text)
    {
        await Task.Delay(millisecondsToWait);
        if (latestTimeOfTyping.Equals(s_lastTimeOfTyping))
        {
            // Execute your function here after last text change
            // Will need to bring back to the UI if doing UI changes
        }
    }
2
répondu Grecon14 2018-02-20 22:07:40

Vous souhaitez utiliser la poignée Quitter ou LostFocus événement pour la zone de texte en question. Je suppose que vous utilisez WinForm même si vous ne l'indiquez pas dans votre question.

1
répondu Jason 2011-11-03 20:37:30

Je ne sais pas si onChange() n'existe que dans une version plus ancienne de c#, mais je ne peux pas le trouver!

les travaux suivants pour détecter quand un utilisateur frappe la touche Enter, ou les onglets hors de la zone de texte, mais seulement après avoir changé quelque texte:

    //--- this block deals with user editing the textBoxInputFile --- //
    private Boolean textChanged = false;
    private void textBoxInputFile_TextChanged(object sender, EventArgs e) {
        textChanged = true;
    }
    private void textBoxInputFile_Leave(object sender, EventArgs e) {
        if (textChanged) {
            fileNameChanged();
        }
        textChanged = false;
    }
    private void textBoxInputFile_KeyDown(object sender, KeyEventArgs e) {
        if (textChanged & e.KeyCode == Keys.Enter) {
            fileNameChanged();
        }
        textChanged = false;
    }
    //--- end block  --- //
1
répondu SurfingSanta 2014-03-05 23:25:10

et si vous déclenchez un événement basé sur une touche comme tab ou return?

0
répondu Mark Kadlec 2011-11-03 20:32:51

un collègue à moi a suggéré une solution en utilisant Rx et l'étouffement d'événement:

var FindDelay = 500;//milliseconds
//textBox is your text box element
Observable.FromEventPattern<EventArgs>(textBox, "TextChanged")
    .Select(ea => ((TextBox) ea.Sender).Text)
    .DistinctUntilChanged()
    .Throttle(TimeSpan.FromMilliseconds(FindDelay))
    .Subscribe(text => { 
        //your handler here 
    });
0
répondu Alex 2018-04-18 19:58:58
public static class UIExtensionMethods
{
    public static async Task<bool> GetIdle(this TextBox txb)
    {
        string txt = txb.Text;
        await Task.Delay(500);
        return txt == txb.Text;
    }
}

Utilisation:

if (await myTextBox.GetIdle()){
    // typing has stopped, do stuff
}
0
répondu fartwhif 2018-10-05 14:45:03