Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Also found the <a href="http://weblogs.asp.net/okloeten/archive/2007/11/12/5088649.aspx" rel="nofollow">AutoFilteredComboBox</a> to be very simple to work with. Though I have made some changes:</p> <ul> <li>Removed use of DependencyPropertyDescriptor to avoid memory leak of combobox-objects</li> <li>Introduced FilterItem-event and FilterList-event to allow one to customize the filtering</li> <li>Changed default filtering from starts-with-string to contains-string</li> <li>Removed support of having IsTextSearchEnabled enabled</li> <li>Shows dropdown as soon one changes the search string, so search result is displayed</li> </ul> <p>Example of how it is used:</p> <pre><code>&lt;Controls:AutoFilteredComboBox ItemsSource="{Binding ViewModel.AvailableItems}" SelectedValue="{Binding ViewModel.SelectedItem, Mode=TwoWay}" IsEditable="True" IsTextSearchEnabled="False"/&gt; </code></pre> <p>Improved version of AutoFilteredComboBox:</p> <pre><code>public class AutoFilteredComboBox : ComboBox { bool _ignoreTextChanged; string _currentText; /// &lt;summary&gt; /// Creates a new instance of &lt;see cref="AutoFilteredComboBox" /&gt;. /// &lt;/summary&gt; public AutoFilteredComboBox() { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) return; } public event Func&lt;object, string, bool&gt; FilterItem; public event Action&lt;string&gt; FilterList; #region IsCaseSensitive Dependency Property /// &lt;summary&gt; /// The &lt;see cref="DependencyProperty"/&gt; object of the &lt;see cref="IsCaseSensitive" /&gt; dependency property. /// &lt;/summary&gt; public static readonly DependencyProperty IsCaseSensitiveProperty = DependencyProperty.Register("IsCaseSensitive", typeof(bool), typeof(AutoFilteredComboBox), new UIPropertyMetadata(false)); /// &lt;summary&gt; /// Gets or sets the way the combo box treats the case sensitivity of typed text. /// &lt;/summary&gt; /// &lt;value&gt;The way the combo box treats the case sensitivity of typed text.&lt;/value&gt; [Description("The way the combo box treats the case sensitivity of typed text.")] [Category("AutoFiltered ComboBox")] [DefaultValue(true)] public bool IsCaseSensitive { [System.Diagnostics.DebuggerStepThrough] get { return (bool)this.GetValue(IsCaseSensitiveProperty); } [System.Diagnostics.DebuggerStepThrough] set { this.SetValue(IsCaseSensitiveProperty, value); } } #endregion #region DropDownOnFocus Dependency Property /// &lt;summary&gt; /// The &lt;see cref="DependencyProperty"/&gt; object of the &lt;see cref="DropDownOnFocus" /&gt; dependency property. /// &lt;/summary&gt; public static readonly DependencyProperty DropDownOnFocusProperty = DependencyProperty.Register("DropDownOnFocus", typeof(bool), typeof(AutoFilteredComboBox), new UIPropertyMetadata(false)); /// &lt;summary&gt; /// Gets or sets the way the combo box behaves when it receives focus. /// &lt;/summary&gt; /// &lt;value&gt;The way the combo box behaves when it receives focus.&lt;/value&gt; [Description("The way the combo box behaves when it receives focus.")] [Category("AutoFiltered ComboBox")] [DefaultValue(false)] public bool DropDownOnFocus { [System.Diagnostics.DebuggerStepThrough] get { return (bool)this.GetValue(DropDownOnFocusProperty); } [System.Diagnostics.DebuggerStepThrough] set { this.SetValue(DropDownOnFocusProperty, value); } } #endregion #region | Handle focus | /// &lt;summary&gt; /// Invoked whenever an unhandled &lt;see cref="UIElement.GotFocus" /&gt; event /// reaches this element in its route. /// &lt;/summary&gt; /// &lt;param name="e"&gt;The &lt;see cref="RoutedEventArgs" /&gt; that contains the event data.&lt;/param&gt; protected override void OnGotFocus(RoutedEventArgs e) { base.OnGotFocus(e); if (this.ItemsSource != null &amp;&amp; this.DropDownOnFocus) { this.IsDropDownOpen = true; } } #endregion public override void OnApplyTemplate() { base.OnApplyTemplate(); AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(OnTextChanged)); KeyUp += AutoFilteredComboBox_KeyUp; this.IsTextSearchEnabled = false; } void AutoFilteredComboBox_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Down) { if (this.IsDropDownOpen == true) { // Ensure that focus is given to the dropdown list if (Keyboard.FocusedElement is TextBox) { Keyboard.Focus(this); if (this.Items.Count &gt; 0) { if (this.SelectedIndex == -1 || this.SelectedIndex==0) this.SelectedIndex = 0; } } } } if (Keyboard.FocusedElement is TextBox) { if (e.OriginalSource is TextBox) { // Avoid the automatic selection of the first letter (As next letter will cause overwrite) TextBox textBox = e.OriginalSource as TextBox; if (textBox.Text.Length == 1 &amp;&amp; textBox.SelectionLength == 1) { textBox.SelectionLength = 0; textBox.SelectionStart = 1; } } } } #region | Handle filtering | private void RefreshFilter() { if (this.ItemsSource != null) { Action&lt;string&gt; filterList = FilterList; if (filterList != null) { filterList(_currentText); } else { ICollectionView view = CollectionViewSource.GetDefaultView(this.ItemsSource); view.Refresh(); } this.SelectedIndex = -1; // Prepare so arrow down selects first this.IsDropDownOpen = true; } } private bool FilterPredicate(object value) { // We don't like nulls. if (value == null) return false; // If there is no text, there's no reason to filter. if (string.IsNullOrEmpty(_currentText)) return true; Func&lt;object, string, bool&gt; filterItem = FilterItem; if (filterItem != null) return filterItem(value, _currentText); if (IsCaseSensitive) return value.ToString().Contains(_currentText); else return value.ToString().ToUpper().Contains(_currentText.ToUpper()); } #endregion protected override void OnSelectionChanged(SelectionChangedEventArgs e) { try { _ignoreTextChanged = true; // Ignore the following TextChanged base.OnSelectionChanged(e); } finally { _ignoreTextChanged = false; } } /// &lt;summary&gt; /// Called when the source of an item in a selector changes. /// &lt;/summary&gt; /// &lt;param name="oldValue"&gt;Old value of the source.&lt;/param&gt; /// &lt;param name="newValue"&gt;New value of the source.&lt;/param&gt; protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue) { if (newValue != null) { ICollectionView view = CollectionViewSource.GetDefaultView(newValue); if (FilterList == null) view.Filter += this.FilterPredicate; } if (oldValue != null) { ICollectionView view = CollectionViewSource.GetDefaultView(oldValue); view.Filter -= this.FilterPredicate; } base.OnItemsSourceChanged(oldValue, newValue); } private void OnTextChanged(object sender, TextChangedEventArgs e) { if (_ignoreTextChanged) return; _currentText = Text; if (!this.IsTextSearchEnabled) { this.RefreshFilter(); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload