ifti24
ifti24

Reputation: 191

Delay timer for KeyDown event

I have a Textbox that has a KeyDown event. This Event is bound with an event handler in the ViewModel. Below is the sample code:

<TextBox x:Name="textBox" Text="{Binding TextBoxText, UpdateSourceTrigger=PropertyChanged}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="KeyDown">
            <cmd:EventToCommand Command="{Binding Path=TextBoxKeyDownEvent}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
<TextBox.InputBindings>

It is true that as soon as the user starts writing in the texbox, the backend event handler in ViewModel is called. But I don't want to call the event handler for each KeyDown operation. I want to call the event handler when the user starts typing in the textbox and stops for at least N milliseconds. That means I need to set a delay timer for the event. Can anyone please guide me how I can achieve that in MVVM?

Upvotes: 2

Views: 1534

Answers (2)

ifti24
ifti24

Reputation: 191

Set a timer and a Time out Event

    private System.Timers.Timer keypressTimer = new System.Timers.Timer();
    keypressTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

Inside the timeout event do your task -

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        keypressTimer.Stop();
        App.Current.Dispatcher.Invoke((Action)delegate
        {

            //CALL YOUR EVENT HERE

        });

    }

Each time the key will be press - you need to reset the timer in the following way.

    if (delayTime > 0)
            {
                keypressTimer.Interval = delayTime;
                keypressTimer.Start();
            }

Upvotes: 1

Adi Lester
Adi Lester

Reputation: 25201

You can make use of the BindingBase.Delay property:

<TextBox x:Name="textBox" Text="{Binding TextBoxText, Delay=500, UpdateSourceTrigger=PropertyChanged}" />

This will modify the TextBoxText property in your viewmodel only 500 milliseconds after it has been changed by the user. Then, in your setter you can call any code you'd like to execute.

private string textBoxText;
public string TextBoxText
{
    get { return textBoxText; }
    set
    {
        // Setter will be called only 500 milliseconds after the user has entered text.
        if (textBoxText != value)
        {
            textBoxText = value;
            RaisePropertyChanged("TextBoxText");

            // Handle text change.
            DoStuff();
        }
    }
}

EDIT:

If you want the delay to happen also when the property is changed in the code, you could use something similar to the solution mentioned here: Timer to fire an event WPF

Upvotes: 7

Related Questions