1

I created a custom DataGridViewComboBoxColumn "TPDataGridViewComboBoxColumn" which inherts from "DataGridViewComboBoxColumn",

public class TPDataGridViewComboBoxColumn : DataGridViewComboBoxColumn {

        public TPDataGridViewComboBoxColumn() {
            CellTemplate = new TPDataGridViewComboBoxCell();
        }

    }

the DataGridViewComboBoxCell "TPDataGridViewComboBoxCell"

public class TPDataGridViewComboBoxCell : DataGridViewComboBoxCell {

        public override Type EditType => typeof(TPDataGridViewComboBoxEditingControl);

    }

and the DataGridViewComboBoxEditingControl "TPDataGridViewComboBoxEditingControl"

public class TPDataGridViewComboBoxEditingControl : DataGridViewComboBoxEditingControl {

        #region Events

        public event EventHandler<OldNewCancelEventArgs> SelectedIndexChanging;
        public event EventHandler<OldNewCancelEventArgs> SelectedValueChanging;

        #endregion Events

        #region Internal Properties

        private int _previousSelectedIndex = -1;
        private bool _isRevertingSelectedIndex = false;

        private object _previousSelectedValue = null;
        private bool _isRevertingSelectedValue = false;

        #endregion Internal Properties

        #region Konstruktor

        public TPDataGridViewComboBoxEditingControl() {
        }

        #endregion Konstruktor

        #region Functions

        protected virtual void OnSelectedValueChanging(OldNewCancelEventArgs e) {
            SelectedValueChanging?.Invoke(this, e);
        }

        protected override void OnSelectedValueChanged(EventArgs e) {
            if (_isRevertingSelectedValue) {
                _isRevertingSelectedValue = false;

                // Ignore the event altogether.
                return;
            }

            var cea = new OldNewCancelEventArgs(_previousSelectedValue, SelectedValue);

            OnSelectedValueChanging(cea);

            if (cea.Cancel) {
                // Revert the index to its previous value, so it appears not to have changed.
                _isRevertingSelectedValue = true;
                SelectedValue = _previousSelectedValue;

                // Do not process the event any further.
                return;
            }

            // Commit the index change.
            _previousSelectedValue = SelectedValue;

            base.OnSelectedValueChanged(e);
        }

        protected virtual void OnSelectedIndexChanging(OldNewCancelEventArgs e) {
            SelectedIndexChanging?.Invoke(this, e);
        }

        protected override void OnSelectedIndexChanged(EventArgs e) {
            if (_isRevertingSelectedIndex) {
                _isRevertingSelectedIndex = false;

                // Ignore the event altogether.
                return;
            }

            var cea = new OldNewCancelEventArgs(_previousSelectedIndex, SelectedIndex);

            OnSelectedIndexChanging(cea);

            if (cea.Cancel) {
                // Revert the index to its previous value, so it appears not to have changed.
                _isRevertingSelectedIndex = true;
                SelectedIndex = _previousSelectedIndex;

                // Do not process the event any further.
                return;
            }

            // Commit the index change.
            _previousSelectedIndex = SelectedIndex;

            base.OnSelectedIndexChanged(e);
        }

        #endregion Functions

    }

I added the datasource for the combobox with some simple strings, and when i want to open the DropDown the SelectedIndex is first set to -1. The CallStack show that scenario: enter image description here

I want to Handle my Custom Event "SelectedValueChanging" to Interrupt the change from one value to another. In the EventHandler i call a MessageBox.Show(). The frequent call of SelectedIndexChanged for a multiple call of MessageBox.Show().

How could i prevent this behavoir?

Thanks in advance!

Edit:

I found out, that in InitializeEditingControl the DataSource is set to NULL and right after that, to my DataSource.

Anton Schrage
  • 1,181
  • 2
  • 14
  • 23
  • 1
    Note: a `MessageBox` isn't an ideal choice for debugging, since it could cause other events to run. Use the debugger to step through the code to examine the values to determine the cause of the problems. – LarsTech Jul 10 '23 at 15:23

1 Answers1

-1

I suggest only invoking your OnSelectedIndexChanged event when the value is different. See the last four lines here:


protected override void OnSelectedIndexChanged(EventArgs e) {
    if (_isRevertingSelectedIndex) {
        _isRevertingSelectedIndex = false;

        // Ignore the event altogether.
        return;
    }

    var cea = new OldNewCancelEventArgs(_previousSelectedIndex, SelectedIndex);

    if (_previousSelectedIndex != SelectedIndex) {
        OnSelectedIndexChanging(cea);
    

    if (cea.Cancel) {
        // Revert the index to its previous value, so it appears not to have changed.
        _isRevertingSelectedIndex = true;
        SelectedIndex = _previousSelectedIndex;

        // Do not process the event any further.
        return;
    }
    }

    // Commit the index change IF CHANGED.
    if (_previousSelectedIndex != SelectedIndex) {
        _previousSelectedIndex = SelectedIndex;

        base.OnSelectedIndexChanged(e);
    }
}
Bron Davies
  • 5,930
  • 3
  • 30
  • 41