Return to Snippet

Revision: 25104
at March 24, 2010 15:39 by alishahnovin


Updated Code
string[] state = new string[] { "Alabama", "Alaska", "Arizona", "Arkansas", "Delaware", "Louisiana", "Maine" };

ComboBox comboBox = new ComboBox();

for (int i = 0; i < state.Length; i++)
{
    ComboBoxItem comboBoxItem = new ComboBoxItem();
    comboBoxItem.Content = state[i];
    comboBox.Items.Add(comboBoxItem);
}

//Must enable keyboard selection **AFTER** it all items have bene added to the ComboBox
comboBox.SetKeyboardSelection(true);


...

public static class Extensions
{
    /*
     * SetKeyboardSelection enables keyboard selection on all
     * ComboBoxItems, as well as on the ComboBox itself (it has not already been added).
     * In addition, it tracks the "search history" that is created as the user types.
     * This is done to allow the user to type in more letters to narrow down
     * results (ie. "Ala" = Alabama, Alaska; "Alab" = Alabama)
     */
    public static void SetKeyboardSelection(this ComboBox comboBox, bool enable)
    {
        string searchStringEnabled = "KeyboardSelectionEnabled";
        string comboBoxTag = comboBox.Tag==null? "" : comboBox.Tag.ToString();
        //See if our search history control already exists by analyzing the combobox tag...
        bool isKeyboardEnabled = comboBoxTag.Contains(searchStringEnabled);

        /*
         * KeyPressSearch is defined as an anonymous delegate, that SetKeyboardSelection delegates
         * to the KeyUp events of ComboBoxItems and the parent ComboBox.
        */
        #region KeyPressSearch
        KeyEventHandler keyPressSearch = delegate(object sender, KeyEventArgs e)
        {
            //Since Key has only certain values, A-Z, D0-D9, NumPad0-9, Space, etc. let's just focus on
            //letters, and numbers, and ignore all other keys... if they're pressed, clear the search history
            //another option is to use PlatformKeyCode, but since it's platform specific, let's not.
            string key = e.Key.ToString();
            if (key.Length > 1 && (key.StartsWith("D") || key.StartsWith("NumPad")))
            { //remove the D/NumPad prefix to get the digit
                key = key.Replace("NumPad", "").Replace("D", "");
            }
            else if (key.Length > 1)
            {
                comboBox.Tag = searchStringEnabled + "||";
                return;
            }
            string searchHistoryPartsString = comboBox.Tag == null ? searchStringEnabled + "||" : comboBox.Tag.ToString();
            string[] searchHistoryParts = (searchHistoryPartsString.Contains("|")) ? searchHistoryPartsString.Split('|') : new string[0];

            int historyExpiration = 1500; //In 1.5 seconds, clear the history, and start new...
            string searchStringHistory = searchHistoryParts.Length == 3 ? searchHistoryParts[1] : "";
            string searchStringTimeStampString = searchHistoryParts.Length == 3 ? searchHistoryParts[2] : "";
            DateTime searchStringTimeStamp;
            string searchString = key;

            if (DateTime.TryParse(searchStringTimeStampString, out searchStringTimeStamp)
                && DateTime.Now.Subtract(searchStringTimeStamp).TotalMilliseconds < historyExpiration)
            {   //search history is valid and has not yet expired...
                searchString = searchStringHistory + key;
            }

            for (int i = 0; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem) &&
                    ((ComboBoxItem)comboBox.Items[i]).Content.ToString().StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase))
                {
                    comboBox.SelectedIndex = i;
                    comboBox.Tag = searchStringEnabled + "|" + searchString + "|" + DateTime.Now;
                    break;
                }
            }
        };
        #endregion

        if (!isKeyboardEnabled && enable)
        {
            comboBox.Tag = searchStringEnabled + "||";

            //Reset the search history on open and close
            comboBox.DropDownOpened += delegate
            {
                comboBox.Tag = searchStringEnabled + "||";
            };
            comboBox.DropDownClosed += delegate
            {
                comboBox.Tag = searchStringEnabled + "||";
            };

            //Add handler to parent control, so that we search even when combobox is closed, yet focused
            comboBox.KeyUp += keyPressSearch;

            for (int i = 0; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem))
                {
                    ((ComboBoxItem)comboBox.Items[i]).KeyUp += keyPressSearch;
                }
            }
        }
        else if (isKeyboardEnabled && !enable)
        {
            //Remove handler
            comboBox.KeyUp -= keyPressSearch;
            for (int i = 0; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem))
                {
                    ((ComboBoxItem)comboBox.Items[i]).KeyUp -= keyPressSearch;
                }
            }
            comboBox.Tag = "";
        }
        else
        {
            //Remove handler
            comboBox.KeyUp -= keyPressSearch;
            comboBox.Tag = "";
        }
    }
}

Revision: 25103
at March 24, 2010 14:31 by alishahnovin


Updated Code
string[] state = new string[] { "Alabama", "Alaska", "Arizona", "Arkansas", "Delaware", "Louisiana", "Maine" };

ComboBox comboBox = new ComboBox();

for (int i = 0; i < state.Length; i++)
{
    ComboBoxItem comboBoxItem = new ComboBoxItem();
    comboBoxItem.Content = state[i];
    comboBox.Items.Add(comboBoxItem);
}

//Must enable keyboard selection **AFTER** it all items have bene added to the ComboBox
comboBox.SetKeyboardSelection(true);


...

public static class Extensions
{
   /*
    * SetKeyboardSelection enables keyboard selection on all
    * ComboBoxItems, as well as on the ComboBox itself (it has not already been added).
    * In addition, it adds a hidden ComboBoxItem that will be used to store the "search history"
    * that is created as the user types. This is done to allow the user to type in more letters to narrow down
    * results (ie. "Ala" = Alabama, Alaska; "Alab" = Alabama)
    */
    public static void SetKeyboardSelection(this ComboBox comboBox, bool enable)
    {
        //Name of ComboBoxItem that will contain the search string history
        string comboBoxName = string.IsNullOrEmpty(comboBox.Name) ? DateTime.Now.Ticks.ToString() : comboBox.Name;
        string searchStringItemName = "KeyboardSelectionSearchString_" + comboBoxName;

        //See if our search history control already exists at index 0, otherwise create it and all necessary events and insert at index 0
        bool isKeyboardEnabled = comboBox.Items[0].GetType() == typeof(ComboBoxItem) && ((ComboBoxItem)comboBox.Items[0]).Name.Contains(searchStringItemName);

        /*
         * KeyPressSearch is defined as an anonymous delegate, that SetKeyboardSelection delegates
         * to the KeyUp events of ComboBoxItems and the parent ComboBox.
        */
        #region KeyPressSearch
        KeyEventHandler keyPressSearch = delegate(object sender, KeyEventArgs e)
        {
            //Since Key has only certain values, A-Z, D0-D9, NumPad0-9, Space, etc. let's just focus on
            //letters, and numbers, and ignore all other keys... if they're pressed, clear the search history
            //another option is to use PlatformKeyCode, but since it's platform specific, let's not.
            string key = e.Key.ToString();
            if (key.Length > 1 && (key.StartsWith("D") || key.StartsWith("NumPad")))
            { //remove the D/NumPad prefix to get the digit
                key = key.Replace("NumPad", "").Replace("D", "");
            }
            else if (key.Length > 1)
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
                return;
            }

            int historyExpiration = 2000; //In 2 seconds, clear the history, and start new...
            string searchStringHistory = ((ComboBoxItem)comboBox.Items[0]).Content.ToString();
            DateTime searchStringTimeStamp;
            string searchString = key;

            if (searchStringHistory.Contains("|")
                && DateTime.TryParse(searchStringHistory.Split('|')[1], out searchStringTimeStamp)
                && DateTime.Now.Subtract(searchStringTimeStamp).TotalMilliseconds < historyExpiration)
            {   //search history is valid and has not yet expired...
                searchString = searchStringHistory.Split('|')[0] + key;
            }

            //Start at 1st index, because 0th index is our search history
            for (int i = 1; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem) &&
                    ((ComboBoxItem)comboBox.Items[i]).Content.ToString().StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase))
                {
                    comboBox.SelectedIndex = i;
                    ((ComboBoxItem)comboBox.Items[0]).Content = searchString + "|" + DateTime.Now;
                    break;
                }
            }
        };
        #endregion

        if (!isKeyboardEnabled && enable)
        {
            ComboBoxItem searchStringItem = new ComboBoxItem();
            searchStringItem.Name = searchStringItemName;
            searchStringItem.Visibility = Visibility.Collapsed;
            searchStringItem.IsEnabled = false;
            searchStringItem.Content = "";

            comboBox.Items.Insert(0, searchStringItem);

            //Ensure that the search history can never be selected
            comboBox.SelectionChanged += delegate
            {
                if (comboBox.SelectedIndex == 0)
                {
                    comboBox.SelectedIndex = 1;
                }
            };

            //Reset the search history on open and close
            comboBox.DropDownOpened += delegate
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
            };
            comboBox.DropDownClosed += delegate
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
            };

            //Add handler to parent contorl, so that we search even when combobox is closed, but focused
            comboBox.KeyUp += keyPressSearch;

            for (int i = 1; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem))
                {
                    ((ComboBoxItem)comboBox.Items[i]).KeyUp += keyPressSearch;
                }
            }
        }
        else if (isKeyboardEnabled && !enable)
        {
            //Remove handler
            comboBox.KeyUp -= keyPressSearch;

            for (int i = 1; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem))
                {
                    ((ComboBoxItem)comboBox.Items[i]).KeyUp -= keyPressSearch;
                }
            }
        }
    }
}

Revision: 25102
at March 24, 2010 11:24 by alishahnovin


Updated Code
string[] state = new string[] { "Alabama", "Alaska", "Arizona", "Arkansas", "Delaware", "Louisiana", "Maine" };

ComboBox comboBox = new ComboBox();

for (int i = 0; i < state.Length; i++)
{
    ComboBoxItem comboBoxItem = new ComboBoxItem();
    comboBoxItem.Content = state[i];
    comboBox.Items.Add(comboBoxItem);
}

//Must enable keyboard selection **AFTER** it all items have bene added to the ComboBox
comboBox.EnableKeyboardSelection();


public static class Extensions
{
       /*
        * EnableKeyboardSelection enables keyboard selection on all
        * ComboBoxItems, as well as on the ComboBox itself (it has not already been added).
        * In addition, it adds a hidden ComboBoxItem that will be used to store the "search history"
        * that is created as the user types. This is done to allow the user to type in more letters to narrow down
        * results (ie. "Ala" = Alabama, Alaska; "Alab" = Alabama)
        */
        public static void EnableKeyboardSelection(this ComboBox comboBox)
        {
            //Name of ComboBoxItem that will contain the search string history
            string comboBoxName = string.IsNullOrEmpty(comboBox.Name) ? DateTime.Now.Ticks.ToString() : comboBox.Name;
            string searchStringItemName = "KeyboardSelectionSearchString_" + comboBoxName;

            //See if our search history control already exists at index 0, otherwise create it and all necessary events and insert at index 0
            bool isKeyboardEnabled = comboBox.Items[0].GetType()==typeof(ComboBoxItem) && ((ComboBoxItem)comboBox.Items[0]).Name.Contains(searchStringItemName);

            if (!isKeyboardEnabled)
            {
                ComboBoxItem searchStringItem = new ComboBoxItem();
                searchStringItem.Name = searchStringItemName;
                searchStringItem.Visibility = Visibility.Collapsed;
                searchStringItem.IsEnabled = false;
                searchStringItem.Content = "";

                comboBox.Items.Insert(0, searchStringItem);

                //Ensure that the search history can never be selected
                comboBox.SelectionChanged += delegate
                {
                    if (comboBox.SelectedIndex == 0)
                    {
                        comboBox.SelectedIndex = 1;
                    }
                };

                //Reset the search history on open and close
                comboBox.DropDownOpened += delegate
                {
                    ((ComboBoxItem)comboBox.Items[0]).Content = "";
                };
                comboBox.DropDownClosed += delegate
                {
                    ((ComboBoxItem)comboBox.Items[0]).Content = "";
                };

                //Add this to parent contorl, so that we search even when combobox is closed, but focused
                comboBox.KeyUp += delegate(object sender, KeyEventArgs e)
                {
                    comboBox.KeyPressSearch(e);
                };

                for (int i = 1; i < comboBox.Items.Count; i++)
                {
                    if (comboBox.Items[i].GetType() == typeof(ComboBoxItem))
                    {
                        ((ComboBoxItem)comboBox.Items[i]).KeyUp += delegate(object sender, KeyEventArgs e)
                        {
                            comboBox.KeyPressSearch(e);
                        };
                    }
                }
            }
        }

       /*
        * KeyPressSearch is a private extension method, that EnableKeyboardSelection delegates
        * to the KeyUp events of ComboBoxItems and the parent ComboBox.
        * 
        * It is set to private because it should only be used via EnableKeyboardSelection.
        */
        private static void KeyPressSearch(this ComboBox comboBox, KeyEventArgs e)
        {
            //Since Key has only certain values, A-Z, D0-D9, NumPad0-9, Space, etc. let's just focus on
            //letters, and numbers, and ignore all other keys... if they're pressed, clear the search history
            //another option is to use PlatformKeyCode, but since it's platform specific, let's not.
            string key = e.Key.ToString();
            if (key.Length > 1 && (key.StartsWith("D") || key.StartsWith("NumPad")))
            { //remove the D/NumPad prefix to get the digit
                key = key.Replace("NumPad", "").Replace("D", "");
            }
            else if (key.Length > 1)
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
                return;
            }

            int historyExpiration = 2000; //In 2 seconds, clear the history, and start new...
            string searchStringHistory = ((ComboBoxItem)comboBox.Items[0]).Content.ToString();
            DateTime searchStringTimeStamp;
            string searchString = key;

            if (searchStringHistory.Contains("|")
                && DateTime.TryParse(searchStringHistory.Split('|')[1], out searchStringTimeStamp)
                && DateTime.Now.Subtract(searchStringTimeStamp).TotalMilliseconds < historyExpiration)
            {   //search history is valid and has not yet expired...
                searchString = searchStringHistory.Split('|')[0] + key;
            }

            //Start at 1st index, because 0th index is our search history
            for (int i = 1; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].GetType() == typeof(ComboBoxItem) && ((ComboBoxItem)comboBox.Items[i]).Content.ToString().StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase))
                {
                    comboBox.SelectedIndex = i;
                    ((ComboBoxItem)comboBox.Items[0]).Content = searchString + "|" + DateTime.Now;
                    break;
                }
            }
        }
}

Revision: 25101
at March 19, 2010 14:31 by alishahnovin


Updated Code
string[] state = new string[] { "Alabama", "Alaska", "Arizona", "Arkansas", "Delaware", "Louisiana", "Maine" };

ComboBox comboBox = new ComboBox();

for (int i = 0; i < state.Length; i++)
{
    ComboBoxItem comboBoxItem = new ComboBoxItem();
    comboBoxItem.Content = state[i];
    comboBox.Items.Add(comboBoxItem);
}

//Must enable keyboard selection **AFTER** it all items have bene added to the ComboBox
comboBox.EnableKeyboardSelection();


public static class Extensions
{
   /*
    * EnableKeyboardSelection enables keyboard selection on all
    * ComboBoxItems, as well as on the ComboBox itself (it has not already been added).
    * In addition, it adds a hidden ComboBoxItem that will be used to store the "search history"
    * that is created as the user types. This is done to allow the user to type in more letters to narrow down
    * results (ie. "Ala" = Alabama, Alaska; "Alab" = Alabama)
    */
    public static void EnableKeyboardSelection(this ComboBox comboBox)
    {
        //Name of ComboBoxItem that will contain the search string history
        string searchStringItemName = "KeyboardSelectionSearchString";

        //See if our search history control already exists at index 0, otherwise create it and all necessary events and insert at index 0
        ComboBoxItem searchStringItem;
        if (!((ComboBoxItem)comboBox.Items[0]).Name.Equals(searchStringItemName))
        {
            searchStringItem = new ComboBoxItem();
            searchStringItem.Name = searchStringItemName;
            searchStringItem.Visibility = Visibility.Collapsed;
            searchStringItem.IsEnabled = false;
            searchStringItem.Content = "";
            comboBox.Items.Insert(0, searchStringItem);

            //Ensure that the search history can never be selected
            comboBox.SelectionChanged += delegate
            {
                if (comboBox.SelectedIndex == 0)
                {
                    comboBox.SelectedIndex = 1;
                }
            };

            //Reset the search history on open and close
            comboBox.DropDownOpened += delegate
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
            };
            comboBox.DropDownClosed += delegate
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
            };

            //Add this to parent contorl, so that we search even when combobox is closed, but focused
            comboBox.KeyUp += delegate(object sender, KeyEventArgs e)
            {
                comboBox.KeyPressSearch(e);
            };

            for (int i = 1; i < comboBox.Items.Count; i++)
            {
                ((ComboBoxItem)comboBox.Items[i]).KeyUp += delegate(object sender, KeyEventArgs e)
                {
                    comboBox.KeyPressSearch(e);
                };
            }
        }
    }

   /*
    * KeyPressSearch is a private extension method, that EnableKeyboardSelection delegates
    * to the KeyUp events of ComboBoxItems and the parent ComboBox.
    * 
    * It is set to private because it should only be used via EnableKeyboardSelection.
    */
    private static void KeyPressSearch(this ComboBox comboBox, KeyEventArgs e)
    {
        //Since Key has only certain values, A-Z, D0-D9, NumPad0-9, Space, etc. let's just focus on
        //letters, and numbers, and ignore all other keys... if they're pressed, clear the search history
        //another option is to use PlatformKeyCode, but since it's platform specific, let's not.
        string key = e.Key.ToString();
        if (key.Length > 1 && (key.StartsWith("D") || key.StartsWith("NumPad")))
        { //remove the D/NumPad prefix to get the digit
            key = key.Replace("NumPad", "").Replace("D", "");
        }
        else if (key.Length > 1)
        {
            ((ComboBoxItem)comboBox.Items[0]).Content = "";
            return;
        }

        int historyExpiration = 2000; //In 2 seconds, clear the history, and start new...
        string searchStringHistory = ((ComboBoxItem)comboBox.Items[0]).Content.ToString();
        DateTime searchStringTimeStamp;
        string searchString = key;

        if (searchStringHistory.Contains("|")
            && DateTime.TryParse(searchStringHistory.Split('|')[1], out searchStringTimeStamp)
            && DateTime.Now.Subtract(searchStringTimeStamp).TotalMilliseconds < historyExpiration)
        {   //search history is valid and has not yet expired...
            searchString = searchStringHistory.Split('|')[0] + key;
        }

        //Start at 1st index, because 0th index is our search history
        for (int i = 1; i < comboBox.Items.Count; i++)
        {
            if (((ComboBoxItem)comboBox.Items[i]).Content.ToString().StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase))
            {
                comboBox.SelectedIndex = i;
                ((ComboBoxItem)comboBox.Items[0]).Content = searchString + "|" + DateTime.Now;
                break;
            }
        }
    }
}

Revision: 25100
at March 19, 2010 14:06 by alishahnovin


Updated Code
string[] state = new string[] { "Alabama", "Alaska", "Arizona", "Arkansas", "Delaware", "Louisiana", "Maine" };

ComboBox comboBox = new ComboBox();

for (int i = 0; i < state.Length; i++)
{
    ComboBoxItem comboBoxItem = new ComboBoxItem();
    comboBoxItem.Content = state[i];
    comboBox.Items.Add(comboBoxItem);
}

//Must enable keyboard selection **AFTER** it all items have bene added to the ComboBox
comboBox.EnableKeyboardSelection();


public static class Extensions
{
   /*
    * EnableKeyboardSelection enables keyboard selection on all
    * ComboBoxItems, as well as on the ComboBox itself (it has not already been added).
    * In addition, it adds a hidden ComboBoxItem that will be used to store the "search history"
    * that is created as the user types. This is done to allow the user to type in more letters to narrow down
    * results (ie. "Ala" = Alabama, Alaska; "Alab" = Alabama)
    */
    public static void EnableKeyboardSelection(this ComboBox comboBox)
    {
        //Name of ComboBoxItem that will contain the search string history
        string searchStringItemName = "KeyboardSelectionSearchString";

        //See if our search history control already exists at index 0, otherwise create it and all necessary events and insert at index 0
        ComboBoxItem searchStringItem;
        if (!((ComboBoxItem)comboBox.Items[0]).Name.Equals(searchStringItemName))
        {
            searchStringItem = new ComboBoxItem();
            searchStringItem.Name = searchStringItemName;
            searchStringItem.Visibility = Visibility.Collapsed;
            searchStringItem.IsEnabled = false;
            searchStringItem.Content = "";
            comboBox.Items.Insert(0, searchStringItem);

            //Ensure that the search history can never be selected
            comboBox.SelectionChanged += delegate
            {
                if (comboBox.SelectedIndex == 0)
                {
                    comboBox.SelectedIndex = 1;
                }
            };

            //Reset the search history on open and close
            comboBox.DropDownOpened += delegate
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
            };
            comboBox.DropDownClosed += delegate
            {
                ((ComboBoxItem)comboBox.Items[0]).Content = "";
            };

            //Add this to parent contorl, so that we search even when combobox is closed, but focused
            comboBox.KeyUp += delegate(object sender, KeyEventArgs e)
            {
                comboBox.KeyPressSearch(e);
            };

            for (int i = 1; i < comboBox.Items.Count; i++)
            {
                ((ComboBoxItem)comboBox.Items[i]).KeyUp += delegate(object sender, KeyEventArgs e)
                {
                    comboBox.KeyPressSearch(e);
                };
            }
        }
    }

   /*
    * KeyPressSearch is a private extension method, that EnableKeyboardSelection delegates
    * to the KeyUp events of ComboBoxItems and the parent ComboBox.
    * 
    * It is set to private because it should only be used via EnableKeyboardSelection.
    */
    private static void KeyPressSearch(this ComboBox comboBox, KeyEventArgs e)
    {
        //Since Key has only certain values, A-Z, D0-D9, NumPad0-9, Space, etc. let's just focus on
        //letters, and numbers, and ignore all other keys... if they're pressed, clear the search history
        //another option is to use PlatformKeyCode, but since it's platform specific, let's not.
        string key = e.Key.ToString();
        if (key.StartsWith("D") || key.StartsWith("NumPad"))
        { //remove the D/NumPad prefix to get the digit
            key = key.Replace("NumPad", "").Replace("D", "");
        }
        else if (key.Length > 1)
        {
            ((ComboBoxItem)comboBox.Items[0]).Content = "";
            return;
        }

        int historyExpiration = 2000; //In 2 seconds, clear the history, and start new...
        string searchStringHistory = ((ComboBoxItem)comboBox.Items[0]).Content.ToString();
        DateTime searchStringTimeStamp;
        string searchString = key;

        if (searchStringHistory.Contains("|")
            && DateTime.TryParse(searchStringHistory.Split('|')[1], out searchStringTimeStamp)
            && DateTime.Now.Subtract(searchStringTimeStamp).TotalMilliseconds < historyExpiration)
        {   //search history is valid and has not yet expired...
            searchString = searchStringHistory.Split('|')[0] + key;
        }

        //Start at 1st index, because 0th index is our search history
        for (int i = 1; i < comboBox.Items.Count; i++)
        {
            if (((ComboBoxItem)comboBox.Items[i]).Content.ToString().StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase))
            {
                comboBox.SelectedIndex = i;
                ((ComboBoxItem)comboBox.Items[0]).Content = searchString + "|" + DateTime.Now;
                break;
            }
        }
    }
}

Revision: 25099
at March 19, 2010 12:20 by alishahnovin


Initial Code
public static class Extensions
{

        public static void EnableKeyboardSelection(this ComboBoxItem comboBoxItem)
        {
            ComboBox parent = (ComboBox)comboBoxItem.Parent;

            //Name of ComboBoxItem that will contain the search string history
            string searchStringItemName = "KeyboardSelectionSearchString";

            //See if our search history control already exists at index 0, otherwise create it and all necessary events and insert at index 0
            ComboBoxItem searchStringItem;
            if (((ComboBoxItem)parent.Items[0]).Name.Equals(searchStringItemName))
            {
                searchStringItem = (ComboBoxItem)parent.Items[0];
            }
            else
            {
                searchStringItem = new ComboBoxItem();
                searchStringItem.Name = searchStringItemName;
                searchStringItem.Visibility = Visibility.Collapsed;
                searchStringItem.IsEnabled = false;
                searchStringItem.Content = "";
                parent.Items.Insert(0, searchStringItem);

                //Ensure that the search history can never be selected
                parent.SelectionChanged += delegate
                {
                    if (parent.SelectedIndex == 0)
                    {
                        parent.SelectedIndex = 1;
                    }
                };

                //Reset the search history on open and close
                parent.DropDownOpened += delegate
                {
                    ((ComboBoxItem)parent.Items[0]).Content = "";
                };
                parent.DropDownClosed += delegate
                {
                    ((ComboBoxItem)parent.Items[0]).Content = "";
                };

                //Add this to parent contorl, so that we search even when combobox is closed, but focused
                parent.KeyUp += delegate(object sender, KeyEventArgs e)
                {
                    ((ComboBox)comboBoxItem.Parent).KeyPressSearch(e);
                };
            }
            
            comboBoxItem.KeyUp += delegate(object sender, KeyEventArgs e)
            {
                ((ComboBox)comboBoxItem.Parent).KeyPressSearch(e);
            };
        }

        private static void KeyPressSearch(this ComboBox parent, KeyEventArgs e)
        {
            //Since Key has only certain values, A-Z, D0-D9, NumPad0-9, Space, etc. let's just focus on
            //letters, and numbers, and ignore all other keys... if they're pressed, clear the search history
            //another option is to use PlatformKeyCode, but since it's platform specific, let's not.
            string key = e.Key.ToString();
            if (key.StartsWith("D") || key.StartsWith("NumPad"))
            { //remove the D/NumPad prefix to get the digit
                key = key.Replace("NumPad", "").Replace("D", "");
            }
            else if (key.Length > 1)
            {
                ((ComboBoxItem)parent.Items[0]).Content = "";
                return;
            }

            int historyExpiration = 2000; //In 2 seconds, clear the history, and start new...
            string searchStringHistory = ((ComboBoxItem)parent.Items[0]).Content.ToString();
            DateTime searchStringTimeStamp;
            string searchString = key;

            if (searchStringHistory.Contains("|")
                && DateTime.TryParse(searchStringHistory.Split('|')[1], out searchStringTimeStamp)
                && DateTime.Now.Subtract(searchStringTimeStamp).TotalMilliseconds < historyExpiration)
            {   //search history is valid and has not yet expired...
                searchString = searchStringHistory.Split('|')[0] + key;
            }

            //Start at 1st index, because 0th index is our search history
            for (int i = 1; i < parent.Items.Count; i++)
            {
                if (((ComboBoxItem)parent.Items[i]).Content.ToString().StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase))
                {
                    parent.SelectedIndex = i;
                    ((ComboBoxItem)parent.Items[0]).Content = searchString + "|" + DateTime.Now;
                    break;
                }
            }
        }
}

Initial URL


Initial Description
I've been trying to figure out a way to make ComboBox items selectable by the keyboard, much like how any ComboBox, ListBox, Selection box is in any other language like HTML, Windows Forms, etc.

Most of the solutions I've seen online weren't particularly useful, or required the use of some third-party DLLs. My solution is a little different, and does not require any new references.

My method works by extending the ComboBox. To use it, all you need to do is call .SetKeyboardSelection() on ComboBox *after* all ComboBoxItems have been added to the ComboBox.

Initial Title
Silverlight ComboBox Keyboard Selection

Initial Tags
event, search

Initial Language
C#