private static void OnSearchModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AutoCompleteTextBox source = d as AutoCompleteTextBox; AutoCompleteSearchMode mode = (AutoCompleteSearchMode)e.NewValue; if (mode != AutoCompleteSearchMode.Contains && mode != AutoCompleteSearchMode.ContainsCaseSensitive && mode != AutoCompleteSearchMode.ContainsOrdinal && mode != AutoCompleteSearchMode.ContainsOrdinalCaseSensitive && mode != AutoCompleteSearchMode.Custom && mode != AutoCompleteSearchMode.Equals && mode != AutoCompleteSearchMode.EqualsCaseSensitive && mode != AutoCompleteSearchMode.EqualsOrdinal && mode != AutoCompleteSearchMode.EqualsOrdinalCaseSensitive && mode != AutoCompleteSearchMode.None && mode != AutoCompleteSearchMode.StartsWith && mode != AutoCompleteSearchMode.StartsWithCaseSensitive && mode != AutoCompleteSearchMode.StartsWithOrdinal && mode != AutoCompleteSearchMode.StartsWithOrdinalCaseSensitive) { source.SetValue(e.Property, e.OldValue); throw new ArgumentException("", "value"); } // Sets the filter predicate for the new value AutoCompleteSearchMode newValue = (AutoCompleteSearchMode)e.NewValue; source.TextFilter = AutoCompleteSearch.GetFilter(newValue); }
/// <summary> /// Performs text completion, if enabled, and a lookup on the underlying /// item values for an exact match. Will update the SelectedItem value. /// </summary> /// <param name="userInitiated">A value indicating whether the operation /// was user initiated. Text completion will not be performed when not /// directly initiated by the user.</param> private void UpdateTextCompletion(bool userInitiated) { // By default this method will clear the selected value object newSelectedItem = null; string text = Text; // Text search is StartsWith explicit and only when enabled, in // line with WPF's ComboBox lookup. When in use it will associate // a Value with the Text if it is found in ItemsSource. This is // only valid when there is data and the user initiated the action. if (View.Count > 0) { if (IsTextCompletionEnabled && TextBox != null && userInitiated) { int currentLength = TextBox.Text.Length; int selectionStart = TextBox.SelectionStart; if (selectionStart == text.Length && selectionStart > TextSelectionStart) { // When the SearchMode dependency property is set to // either StartsWith or StartsWithCaseSensitive, the // first item in the view is used. This will improve // performance on the lookup. It assumes that the // SearchMode the user has selected is an acceptable // case sensitive matching function for their scenario. object top = SearchMode == AutoCompleteSearchMode.StartsWith || SearchMode == AutoCompleteSearchMode.StartsWithCaseSensitive ? View[0] : TryGetMatch(text, View, AutoCompleteSearch.GetFilter(AutoCompleteSearchMode.StartsWith)); // If the search was successful, update SelectedItem if (top != null) { newSelectedItem = top; string topString = FormatValue(top); // Only replace partially when the two words being the same int minLength = Math.Min(topString.Length, Text.Length); if (AutoCompleteSearch.Equals(Text.Substring(0, minLength), topString.Substring(0, minLength))) { // Update the text UpdateTextValue(topString); // Select the text past the user's caret TextBox.SelectionStart = currentLength; TextBox.SelectionLength = topString.Length - currentLength; } } } } else { // Perform an exact string lookup for the text. This is a // design change from the original Toolkit release when the // IsTextCompletionEnabled property behaved just like the // WPF ComboBox's IsTextSearchEnabled property. // // This change provides the behavior that most people expect // to find: a lookup for the value is always performed. newSelectedItem = TryGetMatch(text, View, AutoCompleteSearch.GetFilter(AutoCompleteSearchMode.EqualsCaseSensitive)); } } // Update the selected item property SelectedItem = newSelectedItem; // Restore updates for TextSelection if (IgnoreTextSelectionChange) { IgnoreTextSelectionChange = false; if (TextBox != null) { TextSelectionStart = TextBox.SelectionStart; } } }