/toolkit/Microsoft.Phone.Controls.Toolkit/AutoCompleteBox/AutoCompleteBox.cs
C# | 2678 lines | 1397 code | 254 blank | 1027 comment | 300 complexity | 377f309c4951a40948130697eea689a5 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- // (c) Copyright Microsoft Corporation.
- // This source is subject to the Microsoft Public License (Ms-PL).
- // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
- // All other rights reserved.
-
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Collections.Specialized;
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Controls.Primitives;
- using System.Windows.Data;
- using System.Windows.Input;
- using System.Windows.Markup;
- using System.Windows.Media;
- using System.Windows.Threading;
-
- #if WINDOWS_PHONE
- namespace Microsoft.Phone.Controls
- #else
- namespace System.Windows.Controls
- #endif
- {
- /// <summary>
- /// Represents a control that provides a text box for user input and a
- /// drop-down that contains possible matches based on the input in the text
- /// box.
- /// </summary>
- /// <QualityBand>Stable</QualityBand>
- [TemplatePart(Name = AutoCompleteBox.ElementSelectionAdapter, Type = typeof(ISelectionAdapter))]
- [TemplatePart(Name = AutoCompleteBox.ElementSelector, Type = typeof(Selector))]
- [TemplatePart(Name = AutoCompleteBox.ElementTextBox, Type = typeof(TextBox))]
- [TemplatePart(Name = AutoCompleteBox.ElementPopup, Type = typeof(Popup))]
- [StyleTypedProperty(Property = AutoCompleteBox.ElementTextBoxStyle, StyleTargetType = typeof(TextBox))]
- [StyleTypedProperty(Property = AutoCompleteBox.ElementItemContainerStyle, StyleTargetType = typeof(ListBox))]
- [TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
- [TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)]
- [TemplateVisualState(Name = VisualStates.StatePressed, GroupName = VisualStates.GroupCommon)]
- [TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)]
- [TemplateVisualState(Name = VisualStates.StateFocused, GroupName = VisualStates.GroupFocus)]
- [TemplateVisualState(Name = VisualStates.StateUnfocused, GroupName = VisualStates.GroupFocus)]
- [TemplateVisualState(Name = VisualStates.StatePopupClosed, GroupName = VisualStates.GroupPopup)]
- [TemplateVisualState(Name = VisualStates.StatePopupOpened, GroupName = VisualStates.GroupPopup)]
- [TemplateVisualState(Name = VisualStates.StateValid, GroupName = VisualStates.GroupValidation)]
- [TemplateVisualState(Name = VisualStates.StateInvalidFocused, GroupName = VisualStates.GroupValidation)]
- [TemplateVisualState(Name = VisualStates.StateInvalidUnfocused, GroupName = VisualStates.GroupValidation)]
- [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Large implementation keeps the components contained.")]
- [ContentProperty("ItemsSource")]
- public partial class AutoCompleteBox : Control, IUpdateVisualState
- {
- #region Template part and style names
-
- /// <summary>
- /// Specifies the name of the selection adapter TemplatePart.
- /// </summary>
- private const string ElementSelectionAdapter = "SelectionAdapter";
-
- /// <summary>
- /// Specifies the name of the Selector TemplatePart.
- /// </summary>
- private const string ElementSelector = "Selector";
-
- /// <summary>
- /// Specifies the name of the Popup TemplatePart.
- /// </summary>
- private const string ElementPopup = "Popup";
-
- /// <summary>
- /// The name for the text box part.
- /// </summary>
- private const string ElementTextBox = "Text";
-
- /// <summary>
- /// The name for the text box style.
- /// </summary>
- private const string ElementTextBoxStyle = "TextBoxStyle";
-
- /// <summary>
- /// The name for the adapter's item container style.
- /// </summary>
- private const string ElementItemContainerStyle = "ItemContainerStyle";
-
- #endregion
-
- /// <summary>
- /// Gets or sets a local cached copy of the items data.
- /// </summary>
- private List<object> _items;
-
- /// <summary>
- /// Gets or sets the observable collection that contains references to
- /// all of the items in the generated view of data that is provided to
- /// the selection-style control adapter.
- /// </summary>
- private ObservableCollection<object> _view;
-
- /// <summary>
- /// Gets or sets a value to ignore a number of pending change handlers.
- /// The value is decremented after each use. This is used to reset the
- /// value of properties without performing any of the actions in their
- /// change handlers.
- /// </summary>
- /// <remarks>The int is important as a value because the TextBox
- /// TextChanged event does not immediately fire, and this will allow for
- /// nested property changes to be ignored.</remarks>
- private int _ignoreTextPropertyChange;
-
- /// <summary>
- /// Gets or sets a value indicating whether to ignore calling a pending
- /// change handlers.
- /// </summary>
- private bool _ignorePropertyChange;
-
- /// <summary>
- /// Gets or sets a value indicating whether to ignore the selection
- /// changed event.
- /// </summary>
- private bool _ignoreTextSelectionChange;
-
- /// <summary>
- /// Gets or sets a value indicating whether to skip the text update
- /// processing when the selected item is updated.
- /// </summary>
- private bool _skipSelectedItemTextUpdate;
-
- /// <summary>
- /// Gets or sets the last observed text box selection start location.
- /// </summary>
- private int _textSelectionStart;
-
- /// <summary>
- /// Gets or sets a value indicating whether the user is in the process
- /// of inputting text. This is used so that we do not update
- /// _textSelectionStart while the user is using an IME.
- /// </summary>
- private bool _inputtingText;
-
- /// <summary>
- /// Gets or sets a value indicating whether the user initiated the
- /// current populate call.
- /// </summary>
- private bool _userCalledPopulate;
-
- /// <summary>
- /// A value indicating whether the popup has been opened at least once.
- /// </summary>
- private bool _popupHasOpened;
-
- /// <summary>
- /// Gets or sets the DispatcherTimer used for the MinimumPopulateDelay
- /// condition for auto completion.
- /// </summary>
- private DispatcherTimer _delayTimer;
-
- /// <summary>
- /// Gets or sets a value indicating whether a read-only dependency
- /// property change handler should allow the value to be set. This is
- /// used to ensure that read-only properties cannot be changed via
- /// SetValue, etc.
- /// </summary>
- private bool _allowWrite;
-
- /// <summary>
- /// Gets or sets the helper that provides all of the standard
- /// interaction functionality. Making it internal for subclass access.
- /// </summary>
- internal InteractionHelper Interaction { get; set; }
-
- /// <summary>
- /// Gets or sets the BindingEvaluator, a framework element that can
- /// provide updated string values from a single binding.
- /// </summary>
- private BindingEvaluator<string> _valueBindingEvaluator;
-
- /// <summary>
- /// A weak event listener for the collection changed event.
- /// </summary>
- private WeakEventListener<AutoCompleteBox, object, NotifyCollectionChangedEventArgs> _collectionChangedWeakEventListener;
-
- #region public int MinimumPrefixLength
- /// <summary>
- /// Gets or sets the minimum number of characters required to be entered
- /// in the text box before the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> displays
- /// possible matches.
- /// matches.
- /// </summary>
- /// <value>
- /// The minimum number of characters to be entered in the text box
- /// before the <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" />
- /// displays possible matches. The default is 1.
- /// </value>
- /// <remarks>
- /// If you set MinimumPrefixLength to -1, the AutoCompleteBox will
- /// not provide possible matches. There is no maximum value, but
- /// setting MinimumPrefixLength to value that is too large will
- /// prevent the AutoCompleteBox from providing possible matches as well.
- /// </remarks>
- public int MinimumPrefixLength
- {
- get { return (int)GetValue(MinimumPrefixLengthProperty); }
- set { SetValue(MinimumPrefixLengthProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.MinimumPrefixLength" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.MinimumPrefixLength" />
- /// dependency property.</value>
- public static readonly DependencyProperty MinimumPrefixLengthProperty =
- DependencyProperty.Register(
- "MinimumPrefixLength",
- typeof(int),
- typeof(AutoCompleteBox),
- new PropertyMetadata(1, OnMinimumPrefixLengthPropertyChanged));
-
- /// <summary>
- /// MinimumPrefixLengthProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its MinimumPrefixLength.</param>
- /// <param name="e">Event arguments.</param>
- [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "MinimumPrefixLength is the name of the actual dependency property.")]
- private static void OnMinimumPrefixLengthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- int newValue = (int)e.NewValue;
-
- if (newValue < 0 && newValue != -1)
- {
- throw new ArgumentOutOfRangeException("MinimumPrefixLength");
- }
- }
- #endregion public int MinimumPrefixLength
-
- #region public int MinimumPopulateDelay
- /// <summary>
- /// Gets or sets the minimum delay, in milliseconds, after text is typed
- /// in the text box before the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control
- /// populates the list of possible matches in the drop-down.
- /// </summary>
- /// <value>The minimum delay, in milliseconds, after text is typed in
- /// the text box, but before the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> populates
- /// the list of possible matches in the drop-down. The default is 0.</value>
- /// <exception cref="T:System.ArgumentException">The set value is less than 0.</exception>
- public int MinimumPopulateDelay
- {
- get { return (int)GetValue(MinimumPopulateDelayProperty); }
- set { SetValue(MinimumPopulateDelayProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.MinimumPopulateDelay" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.MinimumPopulateDelay" />
- /// dependency property.</value>
- public static readonly DependencyProperty MinimumPopulateDelayProperty =
- DependencyProperty.Register(
- "MinimumPopulateDelay",
- typeof(int),
- typeof(AutoCompleteBox),
- new PropertyMetadata(OnMinimumPopulateDelayPropertyChanged));
-
- /// <summary>
- /// MinimumPopulateDelayProperty property changed handler. Any current
- /// dispatcher timer will be stopped. The timer will not be restarted
- /// until the next TextUpdate call by the user.
- /// </summary>
- /// <param name="d">AutoCompleteTextBox that changed its
- /// MinimumPopulateDelay.</param>
- /// <param name="e">Event arguments.</param>
- [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "The exception is most likely to be called through the CLR property setter.")]
- private static void OnMinimumPopulateDelayPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
-
- if (source._ignorePropertyChange)
- {
- source._ignorePropertyChange = false;
- return;
- }
-
- int newValue = (int)e.NewValue;
- if (newValue < 0)
- {
- source._ignorePropertyChange = true;
- d.SetValue(e.Property, e.OldValue);
-
- //throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Properties.Resources.AutoComplete_OnMinimumPopulateDelayPropertyChanged_InvalidValue, newValue), "value");
- }
-
- // Stop any existing timer
- if (source._delayTimer != null)
- {
- source._delayTimer.Stop();
-
- if (newValue == 0)
- {
- source._delayTimer = null;
- }
- }
-
- // Create or clear a dispatcher timer instance
- if (newValue > 0 && source._delayTimer == null)
- {
- source._delayTimer = new DispatcherTimer();
- source._delayTimer.Tick += source.PopulateDropDown;
- }
-
- // Set the new tick interval
- if (newValue > 0 && source._delayTimer != null)
- {
- source._delayTimer.Interval = TimeSpan.FromMilliseconds(newValue);
- }
- }
- #endregion public int MinimumPopulateDelay
-
- #region public bool IsTextCompletionEnabled
- /// <summary>
- /// Gets or sets a value indicating whether the first possible match
- /// found during the filtering process will be displayed automatically
- /// in the text box.
- /// </summary>
- /// <value>
- /// True if the first possible match found will be displayed
- /// automatically in the text box; otherwise, false. The default is
- /// false.
- /// </value>
- public bool IsTextCompletionEnabled
- {
- get { return (bool)GetValue(IsTextCompletionEnabledProperty); }
- set { SetValue(IsTextCompletionEnabledProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.IsTextCompletionEnabled" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.IsTextCompletionEnabled" />
- /// dependency property.</value>
- public static readonly DependencyProperty IsTextCompletionEnabledProperty =
- DependencyProperty.Register(
- "IsTextCompletionEnabled",
- typeof(bool),
- typeof(AutoCompleteBox),
- new PropertyMetadata(false, null));
-
- #endregion public bool IsTextCompletionEnabled
-
- #region public DataTemplate ItemTemplate
- /// <summary>
- /// Gets or sets the <see cref="T:System.Windows.DataTemplate" /> used
- /// to display each item in the drop-down portion of the control.
- /// </summary>
- /// <value>The <see cref="T:System.Windows.DataTemplate" /> used to
- /// display each item in the drop-down. The default is null.</value>
- /// <remarks>
- /// You use the ItemTemplate property to specify the visualization
- /// of the data objects in the drop-down portion of the AutoCompleteBox
- /// control. If your AutoCompleteBox is bound to a collection and you
- /// do not provide specific display instructions by using a
- /// DataTemplate, the resulting UI of each item is a string
- /// representation of each object in the underlying collection.
- /// </remarks>
- public DataTemplate ItemTemplate
- {
- get { return GetValue(ItemTemplateProperty) as DataTemplate; }
- set { SetValue(ItemTemplateProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemTemplate" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemTemplate" />
- /// dependency property.</value>
- public static readonly DependencyProperty ItemTemplateProperty =
- DependencyProperty.Register(
- "ItemTemplate",
- typeof(DataTemplate),
- typeof(AutoCompleteBox),
- new PropertyMetadata(null));
-
- #endregion public DataTemplate ItemTemplate
-
- #region public Style ItemContainerStyle
- /// <summary>
- /// Gets or sets the <see cref="T:System.Windows.Style" /> that is
- /// applied to the selection adapter contained in the drop-down portion
- /// of the <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" />
- /// control.
- /// </summary>
- /// <value>The <see cref="T:System.Windows.Style" /> applied to the
- /// selection adapter contained in the drop-down portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// The default is null.</value>
- /// <remarks>
- /// The default selection adapter contained in the drop-down is a
- /// ListBox control.
- /// </remarks>
- public Style ItemContainerStyle
- {
- get { return GetValue(ItemContainerStyleProperty) as Style; }
- set { SetValue(ItemContainerStyleProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemContainerStyle" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemContainerStyle" />
- /// dependency property.</value>
- public static readonly DependencyProperty ItemContainerStyleProperty =
- DependencyProperty.Register(
- ElementItemContainerStyle,
- typeof(Style),
- typeof(AutoCompleteBox),
- new PropertyMetadata(null, null));
-
- #endregion public Style ItemContainerStyle
-
- #region public Style TextBoxStyle
- /// <summary>
- /// Gets or sets the <see cref="T:System.Windows.Style" /> applied to
- /// the text box portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// </summary>
- /// <value>The <see cref="T:System.Windows.Style" /> applied to the text
- /// box portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// The default is null.</value>
- public Style TextBoxStyle
- {
- get { return GetValue(TextBoxStyleProperty) as Style; }
- set { SetValue(TextBoxStyleProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.TextBoxStyle" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.TextBoxStyle" />
- /// dependency property.</value>
- public static readonly DependencyProperty TextBoxStyleProperty =
- DependencyProperty.Register(
- ElementTextBoxStyle,
- typeof(Style),
- typeof(AutoCompleteBox),
- new PropertyMetadata(null));
-
- #endregion public Style TextBoxStyle
-
- #region public double MaxDropDownHeight
- /// <summary>
- /// Gets or sets the maximum height of the drop-down portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// </summary>
- /// <value>The maximum height of the drop-down portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// The default is <see cref="F:System.Double.PositiveInfinity" />.</value>
- /// <exception cref="T:System.ArgumentException">The specified value is less than 0.</exception>
- public double MaxDropDownHeight
- {
- get { return (double)GetValue(MaxDropDownHeightProperty); }
- set { SetValue(MaxDropDownHeightProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.MaxDropDownHeight" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.MaxDropDownHeight" />
- /// dependency property.</value>
- public static readonly DependencyProperty MaxDropDownHeightProperty =
- DependencyProperty.Register(
- "MaxDropDownHeight",
- typeof(double),
- typeof(AutoCompleteBox),
- new PropertyMetadata(double.PositiveInfinity, OnMaxDropDownHeightPropertyChanged));
-
- /// <summary>
- /// MaxDropDownHeightProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteTextBox that changed its MaxDropDownHeight.</param>
- /// <param name="e">Event arguments.</param>
- [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "The exception will be called through a CLR setter in most cases.")]
- private static void OnMaxDropDownHeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
- if (source._ignorePropertyChange)
- {
- source._ignorePropertyChange = false;
- return;
- }
-
- double newValue = (double)e.NewValue;
-
- // Revert to the old value if invalid (negative)
- if (newValue < 0)
- {
- source._ignorePropertyChange = true;
- source.SetValue(e.Property, e.OldValue);
-
- //throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Properties.Resources.AutoComplete_OnMaxDropDownHeightPropertyChanged_InvalidValue, e.NewValue), "value");
- }
-
- source.OnMaxDropDownHeightChanged(newValue);
- }
- #endregion public double MaxDropDownHeight
-
- #region public bool IsDropDownOpen
- /// <summary>
- /// Gets or sets a value indicating whether the drop-down portion of
- /// the control is open.
- /// </summary>
- /// <value>
- /// True if the drop-down is open; otherwise, false. The default is
- /// false.
- /// </value>
- public bool IsDropDownOpen
- {
- get { return (bool)GetValue(IsDropDownOpenProperty); }
- set { SetValue(IsDropDownOpenProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.IsDropDownOpen" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.IsDropDownOpen" />
- /// dependency property.</value>
- public static readonly DependencyProperty IsDropDownOpenProperty =
- DependencyProperty.Register(
- "IsDropDownOpen",
- typeof(bool),
- typeof(AutoCompleteBox),
- new PropertyMetadata(false, OnIsDropDownOpenPropertyChanged));
-
- /// <summary>
- /// IsDropDownOpenProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteTextBox that changed its IsDropDownOpen.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnIsDropDownOpenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
-
- // Ignore the change if requested
- if (source._ignorePropertyChange)
- {
- source._ignorePropertyChange = false;
- return;
- }
-
- bool oldValue = (bool)e.OldValue;
- bool newValue = (bool)e.NewValue;
-
- if (newValue)
- {
- source.TextUpdated(source.Text, true);
- }
- else
- {
- source.ClosingDropDown(oldValue);
- }
-
- source.UpdateVisualState(true);
- }
- #endregion public bool IsDropDownOpen
-
- #region public IEnumerable ItemsSource
- /// <summary>
- /// Gets or sets a collection that is used to generate the items for the
- /// drop-down portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// </summary>
- /// <value>The collection that is used to generate the items of the
- /// drop-down portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.</value>
- public IEnumerable ItemsSource
- {
- get { return GetValue(ItemsSourceProperty) as IEnumerable; }
- set { SetValue(ItemsSourceProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// dependency property.</value>
- public static readonly DependencyProperty ItemsSourceProperty =
- DependencyProperty.Register(
- "ItemsSource",
- typeof(IEnumerable),
- typeof(AutoCompleteBox),
- new PropertyMetadata(OnItemsSourcePropertyChanged));
-
- /// <summary>
- /// ItemsSourceProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its ItemsSource.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox autoComplete = d as AutoCompleteBox;
- autoComplete.OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
- }
-
- #endregion public IEnumerable ItemsSource
-
- #region public object SelectedItem
- /// <summary>
- /// Gets or sets the selected item in the drop-down.
- /// </summary>
- /// <value>The selected item in the drop-down.</value>
- /// <remarks>
- /// If the IsTextCompletionEnabled property is true and text typed by
- /// the user matches an item in the ItemsSource collection, which is
- /// then displayed in the text box, the SelectedItem property will be
- /// a null reference.
- /// </remarks>
- public object SelectedItem
- {
- get { return GetValue(SelectedItemProperty) as object; }
- set { SetValue(SelectedItemProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.SelectedItem" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.SelectedItem" />
- /// dependency property.</value>
- public static readonly DependencyProperty SelectedItemProperty =
- DependencyProperty.Register(
- "SelectedItem",
- typeof(object),
- typeof(AutoCompleteBox),
- new PropertyMetadata(OnSelectedItemPropertyChanged));
-
- /// <summary>
- /// SelectedItemProperty property changed handler. Fires the
- /// SelectionChanged event. The event data will contain any non-null
- /// removed items and non-null additions.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its SelectedItem.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnSelectedItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
-
- if (source._ignorePropertyChange)
- {
- source._ignorePropertyChange = false;
- return;
- }
-
- // Update the text display
- if (source._skipSelectedItemTextUpdate)
- {
- source._skipSelectedItemTextUpdate = false;
- }
- else
- {
- source.OnSelectedItemChanged(e.NewValue);
- }
-
- // Fire the SelectionChanged event
- List<object> removed = new List<object>();
- if (e.OldValue != null)
- {
- removed.Add(e.OldValue);
- }
-
- List<object> added = new List<object>();
- if (e.NewValue != null)
- {
- added.Add(e.NewValue);
- }
-
- source.OnSelectionChanged(new SelectionChangedEventArgs(
- #if !SILVERLIGHT
- SelectionChangedEvent,
- #endif
- removed,
- added));
- }
-
- #if !SILVERLIGHT
- /// <summary>
- /// Declares the routed event for SelectionChanged.
- /// </summary>
- public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent(
- "SelectionChanged", RoutingStrategy.Bubble, typeof(SelectionChangedEventHandler), typeof(AutoCompleteBox));
- #endif
-
- /// <summary>
- /// Called when the selected item is changed, updates the text value
- /// that is displayed in the text box part.
- /// </summary>
- /// <param name="newItem">The new item.</param>
- private void OnSelectedItemChanged(object newItem)
- {
- string text;
-
- if (newItem == null)
- {
- text = SearchText;
- }
- else
- {
- text = FormatValue(newItem, true);
- }
-
- // Update the Text property and the TextBox values
- UpdateTextValue(text);
-
- // Move the caret to the end of the text box
- if (TextBox != null && Text != null)
- {
- TextBox.SelectionStart = Text.Length;
- }
- }
-
- #endregion public object SelectedItem
-
- #region public string Text
- /// <summary>
- /// Gets or sets the text in the text box portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.
- /// </summary>
- /// <value>The text in the text box portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> control.</value>
- public string Text
- {
- get { return GetValue(TextProperty) as string; }
- set { SetValue(TextProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.Text" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.Text" />
- /// dependency property.</value>
- public static readonly DependencyProperty TextProperty =
- DependencyProperty.Register(
- "Text",
- typeof(string),
- typeof(AutoCompleteBox),
- new PropertyMetadata(string.Empty, OnTextPropertyChanged));
-
- /// <summary>
- /// TextProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its Text.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
- source.TextUpdated((string)e.NewValue, false);
- }
-
- #endregion public string Text
-
- #region public string SearchText
- /// <summary>
- /// Gets the text that is used to filter items in the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// item collection.
- /// </summary>
- /// <value>The text that is used to filter items in the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// item collection.</value>
- /// <remarks>
- /// The SearchText value is typically the same as the
- /// Text property, but is set after the TextChanged event occurs
- /// and before the Populating event.
- /// </remarks>
- public string SearchText
- {
- get { return (string)GetValue(SearchTextProperty); }
-
- private set
- {
- try
- {
- _allowWrite = true;
- SetValue(SearchTextProperty, value);
- }
- finally
- {
- _allowWrite = false;
- }
- }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.SearchText" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.SearchText" />
- /// dependency property.</value>
- public static readonly DependencyProperty SearchTextProperty =
- DependencyProperty.Register(
- "SearchText",
- typeof(string),
- typeof(AutoCompleteBox),
- new PropertyMetadata(string.Empty, OnSearchTextPropertyChanged));
-
- /// <summary>
- /// OnSearchTextProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its SearchText.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnSearchTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
- if (source._ignorePropertyChange)
- {
- source._ignorePropertyChange = false;
- return;
- }
-
- // Ensure the property is only written when expected
- if (!source._allowWrite)
- {
- // Reset the old value before it was incorrectly written
- source._ignorePropertyChange = true;
- source.SetValue(e.Property, e.OldValue);
-
- //throw new InvalidOperationException(Properties.Resources.AutoComplete_OnSearchTextPropertyChanged_InvalidWrite);
- }
- }
- #endregion public string SearchText
-
- #region public AutoCompleteFilterMode FilterMode
- /// <summary>
- /// Gets or sets how the text in the text box is used to filter items
- /// specified by the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// property for display in the drop-down.
- /// </summary>
- /// <value>One of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteFilterMode" />
- /// values The default is
- /// <see cref="F:Microsoft.Phone.Controls.AutoCompleteFilterMode.StartsWith" />.</value>
- /// <exception cref="T:System.ArgumentException">The specified value is
- /// not a valid
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteFilterMode" />.</exception>
- /// <remarks>
- /// Use the FilterMode property to specify how possible matches are
- /// filtered. For example, possible matches can be filtered in a
- /// predefined or custom way. The search mode is automatically set to
- /// Custom if you set the ItemFilter property.
- /// </remarks>
- public AutoCompleteFilterMode FilterMode
- {
- get { return (AutoCompleteFilterMode)GetValue(FilterModeProperty); }
- set { SetValue(FilterModeProperty, value); }
- }
-
- /// <summary>
- /// Gets the identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.FilterMode" />
- /// dependency property.
- /// </summary>
- public static readonly DependencyProperty FilterModeProperty =
- DependencyProperty.Register(
- "FilterMode",
- typeof(AutoCompleteFilterMode),
- typeof(AutoCompleteBox),
- new PropertyMetadata(AutoCompleteFilterMode.StartsWith, OnFilterModePropertyChanged));
-
- /// <summary>
- /// FilterModeProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its FilterMode.</param>
- /// <param name="e">Event arguments.</param>
- [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "The exception will be thrown when the CLR setter is used in most situations.")]
- private static void OnFilterModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
- AutoCompleteFilterMode mode = (AutoCompleteFilterMode)e.NewValue;
-
- if (mode != AutoCompleteFilterMode.Contains &&
- mode != AutoCompleteFilterMode.ContainsCaseSensitive &&
- mode != AutoCompleteFilterMode.ContainsOrdinal &&
- mode != AutoCompleteFilterMode.ContainsOrdinalCaseSensitive &&
- mode != AutoCompleteFilterMode.Custom &&
- mode != AutoCompleteFilterMode.Equals &&
- mode != AutoCompleteFilterMode.EqualsCaseSensitive &&
- mode != AutoCompleteFilterMode.EqualsOrdinal &&
- mode != AutoCompleteFilterMode.EqualsOrdinalCaseSensitive &&
- mode != AutoCompleteFilterMode.None &&
- mode != AutoCompleteFilterMode.StartsWith &&
- mode != AutoCompleteFilterMode.StartsWithCaseSensitive &&
- mode != AutoCompleteFilterMode.StartsWithOrdinal &&
- mode != AutoCompleteFilterMode.StartsWithOrdinalCaseSensitive)
- {
- source.SetValue(e.Property, e.OldValue);
-
- //throw new ArgumentException(Properties.Resources.AutoComplete_OnFilterModePropertyChanged_InvalidValue, "value");
- }
-
- // Sets the filter predicate for the new value
- AutoCompleteFilterMode newValue = (AutoCompleteFilterMode)e.NewValue;
- source.TextFilter = AutoCompleteSearch.GetFilter(newValue);
- }
- #endregion public AutoCompleteFilterMode FilterMode
-
- #region public AutoCompleteFilterPredicate ItemFilter
- /// <summary>
- /// Gets or sets the custom method that uses user-entered text to filter
- /// the items specified by the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// property for display in the drop-down.
- /// </summary>
- /// <value>The custom method that uses the user-entered text to filter
- /// the items specified by the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// property. The default is null.</value>
- /// <remarks>
- /// The filter mode is automatically set to Custom if you set the
- /// ItemFilter property.
- /// </remarks>
- public AutoCompleteFilterPredicate<object> ItemFilter
- {
- get { return GetValue(ItemFilterProperty) as AutoCompleteFilterPredicate<object>; }
- set { SetValue(ItemFilterProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemFilter" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemFilter" />
- /// dependency property.</value>
- public static readonly DependencyProperty ItemFilterProperty =
- DependencyProperty.Register(
- "ItemFilter",
- typeof(AutoCompleteFilterPredicate<object>),
- typeof(AutoCompleteBox),
- new PropertyMetadata(OnItemFilterPropertyChanged));
-
- /// <summary>
- /// ItemFilterProperty property changed handler.
- /// </summary>
- /// <param name="d">AutoCompleteBox that changed its ItemFilter.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnItemFilterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AutoCompleteBox source = d as AutoCompleteBox;
- AutoCompleteFilterPredicate<object> value = e.NewValue as AutoCompleteFilterPredicate<object>;
-
- // If null, revert to the "None" predicate
- if (value == null)
- {
- source.FilterMode = AutoCompleteFilterMode.None;
- }
- else
- {
- source.FilterMode = AutoCompleteFilterMode.Custom;
- source.TextFilter = null;
- }
- }
- #endregion public AutoCompleteFilterPredicate ItemFilter
-
- #region public AutoCompleteStringFilterPredicate TextFilter
- /// <summary>
- /// Gets or sets the custom method that uses the user-entered text to
- /// filter items specified by the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// property in a text-based way for display in the drop-down.
- /// </summary>
- /// <value>The custom method that uses the user-entered text to filter
- /// items specified by the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.ItemsSource" />
- /// property in a text-based way for display in the drop-down.</value>
- /// <remarks>
- /// The search mode is automatically set to Custom if you set the
- /// TextFilter property.
- /// </remarks>
- public AutoCompleteFilterPredicate<string> TextFilter
- {
- get { return GetValue(TextFilterProperty) as AutoCompleteFilterPredicate<string>; }
- set { SetValue(TextFilterProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.TextFilter" />
- /// dependency property.
- /// </summary>
- /// <value>The identifier for the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.TextFilter" />
- /// dependency property.</value>
- public static readonly DependencyProperty TextFilterProperty =
- DependencyProperty.Register(
- "TextFilter",
- typeof(AutoCompleteFilterPredicate<string>),
- typeof(AutoCompleteBox),
- new PropertyMetadata(AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith)));
- #endregion public AutoCompleteStringFilterPredicate TextFilter
-
- #if WINDOWS_PHONE
- #region public InputScope InputScope
- /// <summary>
- /// Gets or sets the
- /// <see cref="T:System.Windows.Input.InputScope"/>
- /// used by the Text template part.
- /// </summary>
- public InputScope InputScope
- {
- get { return (InputScope)GetValue(InputScopeProperty); }
- set { SetValue(InputScopeProperty, value); }
- }
-
- /// <summary>
- /// Identifies the
- /// <see cref="P:Microsoft.Phone.Controls.AutoCompleteBox.InputScope"/>
- /// dependency property.
- /// </summary>
- public static readonly DependencyProperty InputScopeProperty =
- DependencyProperty.Register(
- "InputScope",
- typeof(InputScope),
- typeof(AutoCompleteBox),
- null);
- #endregion public InputScope InputScope
- #endif
-
- #region Template parts
-
- /// <summary>
- /// Gets or sets the drop down popup control.
- /// </summary>
- private PopupHelper DropDownPopup { get; set; }
-
- /// <summary>
- /// Determines whether text completion should be done.
- /// </summary>
- private static bool IsCompletionEnabled
- {
- get
- {
- PhoneApplicationFrame frame;
- return PhoneHelper.TryGetPhoneApplicationFrame(out frame) && frame.IsPortrait();
- }
- }
-
- /// <summary>
- /// The TextBox template part.
- /// </summary>
- private TextBox _text;
-
- /// <summary>
- /// The SelectionAdapter.
- /// </summary>
- private ISelectionAdapter _adapter;
-
- /// <summary>
- /// Gets or sets the Text template part.
- /// </summary>
- internal TextBox TextBox
- {
- get { return _text; }
- set
- {
- // Detach existing handlers
- if (_text != null)
- {
- _text.SelectionChanged -= OnTextBoxSelectionChanged;
- _text.TextChanged -= OnTextBoxTextChanged;
- }
-
- _text = value;
-
- // Attach handlers
- if (_text != null)
- {
- _text.SelectionChanged += OnTextBoxSelectionChanged;
- _text.TextChanged += OnTextBoxTextChanged;
-
- if (Text != null)
- {
- UpdateTextValue(Text);
- }
- }
- }
- }
-
- /// <summary>
- /// Gets or sets the selection adapter used to populate the drop-down
- /// with a list of selectable items.
- /// </summary>
- /// <value>The selection adapter used to populate the drop-down with a
- /// list of selectable items.</value>
- /// <remarks>
- /// You can use this property when you create an automation peer to
- /// use with AutoCompleteBox or deriving from AutoCompleteBox to
- /// create a custom control.
- /// </remarks>
- protected internal ISelectionAdapter SelectionAdapter
- {
- get { return _adapter; }
- set
- {
- if (_adapter != null)
- {
- _adapter.SelectionChanged -= OnAdapterSelectionChanged;
- _adapter.Commit -= OnAdapterSelectionComplete;
- _adapter.Cancel -= OnAdapterSelectionCanceled;
- _adapter.Cancel -= OnAdapterSelectionComplete;
- _adapter.ItemsSource = null;
- }
-
- _adapter = value;
-
- if (_adapter != null)
- {
- _adapter.SelectionChanged += OnAdapterSelectionChanged;
- _adapter.Commit += OnAdapterSelectionComplete;
- _adapter.Cancel += OnAdapterSelectionCanceled;
- _adapter.Cancel += OnAdapterSelectionComplete;
- _adapter.ItemsSource = _view;
- }
- }
- }
-
- #endregion
-
- /// <summary>
- /// Occurs when the text in the text box portion of the
- /// <see cref="T:Microsoft.Phone.Controls.AutoCompleteBox" /> changes.
- …
Large files files are truncated, but you can click here to view the full file