Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# set UserControl.Value without invoking the ValueChanged event

I running into an infinite loop problem.

I have two numeric up/down controls (Height and Width input parameters). When the user changes the value of one of the controls, I need to scale the other to keep a height to width ratio constant.

Is there a way to set the value of a control without invoking a ValueChanged Event. I only want the ValueChanged event to execute when the user changes the value.

private void FloorLength_ValueChanged(object sender, EventArgs e)
{
    if (this.mCurrentDocument.System.SuperTrakSystem.FloorBitmap != null)
    {
        FloorWidth.Value = FloorLength.Value * 
            ((decimal)this.mCurrentDocument.System.SuperTrakSystem.FloorBitmap.Height / 
            (decimal)this.mCurrentDocument.System.SuperTrakSystem.FloorBitmap.Width);
    }
}

private void FloorWidth_ValueChanged(object sender, EventArgs e)
{
    if (this.mCurrentDocument.System.SuperTrakSystem.FloorBitmap != null)
    {
        FloorLength.Value = FloorWidth.Value * 
            ((decimal)this.mCurrentDocument.System.SuperTrakSystem.FloorBitmap.Width / 
            (decimal)this.mCurrentDocument.System.SuperTrakSystem.FloorBitmap.Height);
    }
}
like image 208
Kevin Avatar asked Feb 09 '10 16:02

Kevin


3 Answers

Thanks for your answers.

I came up with an alternate solution that works. User changing the value from the UI triggers the event, while programmatic Value parameter changes do not trigger the event.

using System;
using System.Windows.Forms;

namespace myNameSpace.Forms.UserControls
{
    public class NumericUpDownSafe : NumericUpDown
    {
        EventHandler eventHandler = null;

        public event EventHandler ValueChanged
        {
            add
            {
                eventHandler += value;
                base.ValueChanged += value;
            }

            remove
            {
                eventHandler -= value;
                base.ValueChanged -= value;
            }
        }

        public decimal Value
        {
            get
            {
                return base.Value;
            }
            set
            {
                base.ValueChanged -= eventHandler;
                base.Value = value;
                base.ValueChanged += eventHandler;
            }
        }
    }
}
like image 141
Kevin Avatar answered Oct 24 '22 03:10

Kevin


I'm not that familiar with the NumericUpDown control, but there may not be a way to set the value without triggering the ValueChanged event. Instead, before you set the value, you could set a flag indicating that the event should be ignored, and clear the flag after setting the value. In your event handler, do nothing if the flag is set.

private bool ignoreEvent = false;
private void setValue(int value)
{
    ignoreEvent = true;
    FloorLength.Value = value;
    ignoreEvent = false;
}

private void FloorLength_ValueChanged(object sender, EventArgs e)
{
    if(ignoreEvent) { return; }

    // your code here
}
like image 30
Kevin Kibler Avatar answered Oct 24 '22 03:10

Kevin Kibler


In theory, these values should stabilize... Meaning if the user changes 1, the system changes the other and then the first one remains the same. Therefore, I would just add a check into both of the event handlers (pseudocode):

newValue = equation;
if(controlValue != newValue)  
{
    controlValue = newValue; //raises the event only when necessary.
}
like image 1
Jacob G Avatar answered Oct 24 '22 04:10

Jacob G