3

I have a numericUpDown control (Windows Forms).

enter image description here

I want to listen to the ValueChanged event.

I set it in the properties and it works.

But:

I want that i can "scroll" up or down. (If I make this longer it will be faster)

When I'm done with the "scroll", I want that the event xyz is fired now and not during the scrolling.

How can I do that?

1
  • How you could tell to your code When I'm done with the "scroll". If you need to validate the numeric input then use the Validating event (when you leave the control) Commented Aug 2, 2012 at 9:12

4 Answers 4

1

Try using the mouseup event. It fires when you take your finger off of the left mouse button, so in theory it should solve your issue.

[Edited by James] Try this control on your form.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Example.CustomControl
{
    /// <summary>
    /// Provides an extra event for the numericUpDown control that fires after the value stops scrolling.
    /// </summary>
    public class NumericDelayedChange : NumericUpDown
    {
        /// <summary>
        /// Flag that the value has actually changed.
        /// </summary>
        /// <devdoc>
        /// Just in case the control was clicked somewhere other than the up/down buttons.
        /// </devdoc>
        private bool valueHasChanged = false;

        /// <summary>
        /// Fires when the value has stopped being scrolled.
        /// </summary>
        public event EventHandler OnAfterScollValueChanged;

        /// <summary>
        /// Captures that value as having changed.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnValueChanged(EventArgs e)
        {
            valueHasChanged = true;
            base.OnValueChanged(e);
        }

        /// <summary>
        /// Captures the mouse up event to identify scrolling stopped when used in combination with the value changed flag.
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            base.OnMouseUp(mevent);
            if (mevent.Button == System.Windows.Forms.MouseButtons.Left)
            {
                PerformOnAfterScollValueChanged();
            }
        }

        /// <summary>
        /// Captures the key up/down events to identify scrolling stopped when used in combination with the value changed flag.
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
            {
                PerformOnAfterScollValueChanged();
            }
            base.OnKeyUp(e);
        }

        /// <summary>
        /// Checks the value changed flag and fires the OnAfterScollValueChanged event.
        /// </summary>
        private void PerformOnAfterScollValueChanged()
        {
            if (valueHasChanged)
            {
                valueHasChanged = false;
                if (OnAfterScollValueChanged != null) { OnAfterScollValueChanged(this, new EventArgs()); }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Isn't the control scrolled using up/down cursor keys to? The mouse up will not fire in this case.
I guess add the same logic to the cursor key too. I.e. key up where the key is a cursor key as well as the mouse up.
In that case, create a sub to handle what you want to do and call it on the MouseUp and the KeyUp events (if the key ups are of the arrow keys, and the NumericUpDown has focus).
I actually have a working example but don't wnat to steal your thunder! Can I edit you answer?
Go ahead, I've only been learning C# for the last week, up until then I've only had about 6-8 months of VB experience. I'm certainly no pro, just mildly adept.
1

You need to define what is I'm done with the scroll. This could be removing the mouse from the scroll button, or a certain time passed since the last click. In any case, I don't think you can cause the event not to run, but you can do some checks in the event handler. For example:

private DateTime? lastClickTime;
public void MyUpDown_ValueChanged(object sender, EventArgs e)
{
    if (lastClickTime != null && DateTime.Now.Subtract(lastClickTime.Value).Seconds > someInterval)
    {
        // Do the work
    }

    lastClickTime = DateTime.Now
}

But, as I said, you need first to define what is I'm done. This code is not perfect.

Comments

0

Here's a direct way of approaching the problem: Just check if a mouse button is being pressed with Control.MouseButtons, like this:

private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
        //don't update until done scrolling
        if (Control.MouseButtons == MouseButtons.None)
        {
            // Do the work
        }
    }

Comments

0

Here's how I solved this problem:

A task checks a "valueIsChanging" flag. This flag is set by the ValueChanged event. After this flag stops being set to True by the ValueChanged event, the while loop completes and your code is executed.

Task waitForValueSettleTask;
volatile bool valueIsChanging; // marked volaltile since it is access by multiple threads (the GUI thread, and the task)

private void numericUpDown_ValueChanged(object sender, EventArgs e)
{
    valueIsChanging = true;

    if (waitForValueSettleTask == null || waitForValueSettleTask != null &&
    (waitForValueSettleTask.IsCanceled || waitForValueSettleTask.IsCompleted || waitForValueSettleTask.IsFaulted))
    {
        waitForValueSettleTask = Task.Run(() =>
        {
            while (valueIsChanging)
            {
                valueIsChanging = false;
                Thread.Sleep(1000); // Set this to whatever settling time you'd like
            }

            // Your code goes here
        });
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.