WPF Ribbon - Alt + code not working

Sep 7, 2011 at 10:47 PM

The users are not able to enter ALT + code characters (e.g. ALT+0176 for the degree symbol) in textboxes anymore when these are placed on a WPF Ribbon window.

I dived in the source code and quickly found that the problem is caused by the KeyTipService. Please replace the OnPreviewTextInput and OnKeyTipPartialMatch in KeyTipService.cs with these ones, this will allow “alt + code characters“ again just as in Microsoft Word.

 private void OnPreviewTextInput(TextCompositionEventArgs textArgs)
        {
            string text = textArgs.Text;
            if (string.IsNullOrEmpty(text))
            {
                text = textArgs.SystemText;
            }

            if (string.IsNullOrEmpty(text))
            {
                return;
            }

 

            if (text == " ")
            {
                // Do nothing. 
            }
            else 
            {
                if (State == KeyTipState.Pending)
                {
                    ShowKeyTips();
                }
 
                if (_currentActiveKeyTipElements.Count > 0)
                {
                    if (_probableModeEnterKey != Key.None &&
                        _modeEnterKey == Key.None)
                    {
                        // When text is pressed, probableModeEnterKey becomes 
                        // modeEnterKey. KeyTips are not dismissed on up of
                        // modeEnterKey for once. This is useful when multiple
                        // text is pressed with alt pressed.
                        _modeEnterKey = _probableModeEnterKey;
                        _probableModeEnterKey = Key.None;
                    }

                    text = _prefixText + text;
                    //CHANGE 1: dont set args.Handled = true;

                    DependencyObject exactMatchElement = null;
                    List<DependencyObject> activeKeyTipElements = FindKeyTipMatches(text, out exactMatchElement);

                    if (exactMatchElement != null)
                    {
                        OnKeyTipExactMatch(exactMatchElement);
                        // CHANGE 2: set args.Handled = true (found match)
                        textArgs.Handled = true;
                    }
                    else
                    {
                        bool cancel;
                        OnKeyTipPartialMatch(activeKeyTipElements, text, out cancel);
                       //CHANGE 3: only set args.handled when a partial match was found
                        textArgs.Handled = textArgs.Handled || !cancel;
                    }
                }
            }
        }

 
        //CHANGE 4: change signature
        private void OnKeyTipPartialMatch(List<DependencyObject> activeKeyTipElements, string text, out bool cancel)
        {
            if (activeKeyTipElements == null || 
                activeKeyTipElements.Count == 0)
            {
                // Beep when there are no matches.
                RibbonHelper.Beep();
 
                // CHANGE 5: report back to calling method that there are no matches found
                cancel = true;
                return;
            }
 
            int currentActiveCount = _currentActiveKeyTipElements.Count;
            int newActiveCount = activeKeyTipElements.Count;
            int newActiveElementIndex = 0;
            DependencyObject newActiveElement = activeKeyTipElements[newActiveElementIndex++];
 
            // Hide keytips for all the elements which do not
            // match with the new prefix.
            for (int i = 0; i < currentActiveCount; i++)
            {
                DependencyObject currentActiveElement = _currentActiveKeyTipElements[i];
                if (currentActiveElement == newActiveElement)
                {
                    if (newActiveElementIndex < newActiveCount)
                    {
                        newActiveElement = activeKeyTipElements[newActiveElementIndex++];
                    }
                    else
                    {
                        newActiveElement = null;
                    }
                }
                else
                {
                    HideKeyTipForElement(currentActiveElement);
                }
            }
            _currentActiveKeyTipElements = activeKeyTipElements;
            _prefixText = text;

            //CHANGE 6
            cancel = false;
        }