Why does SelectedIndexChanged is called with -1 on EditingControlShowing?

39 Views Asked by At

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.

1

There are 1 best solutions below

3
Bron Davies On

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);
    }
}