Forcing My Hand - One Hand That Is

September 8th, 2006

So, you’re building a Pocket PC application against the .NET Compact Framework 1.0 and you want to support one hand operation.  You have a ComboBox nestled between two other controls.  Once you get focus on the ComboBox, how do you allow the user to get off the ComboBox control?  D-Pad navigation would be the way to go. However, the Up AND Left keys change the control’s selection to the previous value in the list, and the Down AND Right keys change the selection to the next value in the list.

It would be cool if the Up and Down keys let you move to the Previous/Next control (like on the Smartphone).  So, you think you can capture the KeyDown event, handle the event, and you are good to go… something like this would seem to do the trick:

        public Control GetNextControl(Control ctl, bool forward)
        {
            int curIndex = this.Controls.IndexOf(ctl);
            if (forward)
            {
                if (curIndex < this.Controls.Count)
                    curIndex++;
                else
                    curIndex = 0;
            }
            else
            {
                if (curIndex > 0)
                    curIndex- -;
                else
                    curIndex = this.Controls.Count - 1;
            }

            return this.Controls[curIndex];
        }

        private void comboBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)
            {

                // Move to the previous control and handle the event
                GetNextControl(this, false).Focus();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Down)
            {

                // Move to the next control and handle the event
                GetNextControl(this, true).Focus();
                e.Handled = true;
            }
        }

It doesn’t work… the focus changes to the proper control which is cool, but the combobox’s selected value still changes.  At this point you might get a bit annoyed and after a cup of coffee and chilling out, you end up with something like this:

        // Keep track of the previous selected index
        int previousIndex = -1;
        private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (previousIndex != -1)
            {
                ((ComboBox)sender).SelectedIndex = previousIndex;
                // Reset this to -1 so we only fire this logic when Up or Down is pressed
                previousIndex = -1;
            }
        }

        private void comboBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)
            {
                GetNextControl(this, false).Focus();
                // e.Handled = true; THIS DOES NOT APPEAR TO FUNCTION PROPERLY
                previousIndex = ((ComboBox)sender).SelectedIndex;
            }
            else if (e.KeyCode == Keys.Down)
            {
                GetNextControl(this, true).Focus();
                // e.Handled = true; THIS DOES NOT APPEAR TO FUNCTION PROPERLY
                previousIndex = ((ComboBox)sender).SelectedIndex;
            }
        }

        private void comboBox_GotFocus(object sender, EventArgs e)
        {
            // If the behavior is as we expect (ie, Smartphone) make sure that works too!
            previousIndex = -1;
        }

It’s a bit of a kludge, but it worked for me.  Hope this helps.

-kevin

Entry Filed under: Mobile