4 using System.Collections;
 
    6 using System.Threading.Tasks;
 
    8 using System.Windows.Controls;
 
    9 using System.Windows.Controls.Primitives;
 
   10 using System.Windows.Data;
 
   11 using System.Windows.Input;
 
   13 using SiliconStudio.Presentation.Core;
 
   14 using SiliconStudio.Presentation.Extensions;
 
   16 namespace SiliconStudio.Presentation.Controls
 
   18     [TemplatePart(Name = 
"PART_EditableTextBox", Type = typeof(TextBox))]
 
   19     [TemplatePart(Name = 
"PART_ListBox", Type = typeof(ListBox))]
 
   25             private string tokenLowercase;
 
   27             public string Token { 
get { 
return token; } set { token = value; tokenLowercase = (value ?? 
"").ToLowerInvariant(); } }
 
   34                 if (
string.IsNullOrWhiteSpace(token))
 
   35                     return string.Compare(a, b, StringComparison.InvariantCultureIgnoreCase);
 
   37                 var indexA = a.IndexOf(tokenLowercase, StringComparison.InvariantCultureIgnoreCase);
 
   38                 var indexB = b.IndexOf(tokenLowercase, StringComparison.InvariantCultureIgnoreCase);
 
   40                 if (indexA == 0 && indexB > 0)
 
   42                 if (indexB == 0 && indexA > 0)
 
   45                 return string.Compare(
a, 
b, StringComparison.InvariantCultureIgnoreCase);
 
   52         private readonly FilteringComboBoxSort sort;
 
   57         private TextBox editableTextBox;
 
   62         private ListBox listBox;
 
   67         private bool clearing;
 
   71         private bool updatingSelection;
 
   76         private bool validating;
 
   78         public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register(
"IsDropDownOpen", typeof(
bool), typeof(
FilteringComboBox));
 
   80         public static readonly DependencyProperty ClearTextAfterValidationProperty = DependencyProperty.Register(
"ClearTextAfterValidation", typeof(
bool), typeof(
FilteringComboBox));
 
   85         public static readonly DependencyProperty WatermarkContentProperty = DependencyProperty.Register(
"WatermarkContent", typeof(
object), typeof(
FilteringComboBox), 
new PropertyMetadata(null));
 
   87         public static readonly DependencyProperty ItemsToExcludeProperty = DependencyProperty.Register(
"ItemsToExclude", typeof(
IEnumerable), typeof(
FilteringComboBox));
 
   97         public static readonly RoutedEvent ValidatedEvent = EventManager.RegisterRoutedEvent(
"Validated", RoutingStrategy.Bubble, typeof(ValidationRoutedEventHandler<string>), typeof(
FilteringComboBox));
 
  102             IsTextSearchEnabled = 
false;
 
  105         public bool IsDropDownOpen { 
get { 
return (
bool)GetValue(IsDropDownOpenProperty); } set { SetValue(IsDropDownOpenProperty, value); } }
 
  107         public bool ClearTextAfterValidation { 
get { 
return (
bool)GetValue(ClearTextAfterValidationProperty); } set { SetValue(ClearTextAfterValidationProperty, value); } }
 
  112         public object WatermarkContent { 
get { 
return GetValue(WatermarkContentProperty); } set { SetValue(WatermarkContentProperty, value); } }
 
  114         public IEnumerable ItemsToExclude { 
get { 
return (
IEnumerable)GetValue(ItemsToExcludeProperty); } set { SetValue(ItemsToExcludeProperty, value); } }
 
  119         public event CancelRoutedEventHandler Validating { add { AddHandler(ValidatingEvent, value); } 
remove { RemoveHandler(ValidatingEvent, value); } }
 
  124         public event ValidationRoutedEventHandler<string> Validated { add { AddHandler(ValidatedEvent, value); } 
remove { RemoveHandler(ValidatedEvent, value); } }
 
  128             base.OnItemsSourceChanged(oldValue, newValue);
 
  129             if (newValue != null)
 
  131                 var cvs = (CollectionView)CollectionViewSource.GetDefaultView(newValue);
 
  133                 var listCollectionView = cvs as ListCollectionView;
 
  134                 if (listCollectionView != null)
 
  136                     listCollectionView.CustomSort = sort;
 
  143             base.OnApplyTemplate();
 
  145             editableTextBox = GetTemplateChild(
"PART_EditableTextBox") as 
TextBox;
 
  146             if (editableTextBox == null)
 
  147                 throw new InvalidOperationException(
"A part named 'PART_EditableTextBox' must be present in the ControlTemplate, and must be of type 'SiliconStudio.Presentation.Controls.Input.TextBox'.");
 
  149             listBox = GetTemplateChild(
"PART_ListBox") as ListBox;
 
  151                 throw new InvalidOperationException(
"A part named 'PART_ListBox' must be present in the ControlTemplate, and must be of type 'ListBox'.");
 
  153             editableTextBox.TextChanged += EditableTextBoxTextChanged;
 
  154             editableTextBox.PreviewKeyDown += EditableTextBoxPreviewKeyDown;
 
  155             editableTextBox.Validating += EditableTextBoxValidating;
 
  156             editableTextBox.Validated += EditableTextBoxValidated;
 
  157             editableTextBox.Cancelled += EditableTextBoxCancelled;
 
  158             editableTextBox.LostFocus += EditableTextBoxLostFocus;
 
  159             listBox.PreviewMouseUp += ListBoxMouseUp;
 
  164             base.OnSelectionChanged(e);
 
  165             if (SelectedItem == null && !updatingSelection)
 
  168                 editableTextBox.Clear();
 
  173         private void UpdateText()
 
  175             if (listBox.SelectedItem != null)
 
  177                 editableTextBox.Text = listBox.SelectedItem.ToString();
 
  178                 IsDropDownOpen = 
false;
 
  185             if (!ReferenceEquals(sender, editableTextBox))
 
  193             RaiseEvent(cancelRoutedEventArgs);
 
  194             if (cancelRoutedEventArgs.Cancel)
 
  201             if (!ReferenceEquals(sender, editableTextBox))
 
  205             RaiseEvent(validatedArgs);
 
  207             if (ClearTextAfterValidation)
 
  210                 editableTextBox.Text = string.Empty;
 
  215         private async 
void EditableTextBoxCancelled(
object sender, 
RoutedEventArgs e)
 
  218             if (!ReferenceEquals(sender, editableTextBox))
 
  222             editableTextBox.Text = string.Empty;
 
  225             await Task.Delay(100);
 
  226             IsDropDownOpen = 
false;
 
  230         private async 
void EditableTextBoxLostFocus(
object sender, 
RoutedEventArgs e)
 
  233             if (!ReferenceEquals(sender, editableTextBox))
 
  239             await Task.Delay(100);
 
  240             IsDropDownOpen = 
false;
 
  244         private void ListBoxMouseUp(
object sender, MouseButtonEventArgs e)
 
  246             if (e.ChangedButton == 
MouseButton.Left && listBox.SelectedIndex > -1)
 
  249                 editableTextBox.Validate();
 
  253         private void EditableTextBoxTextChanged(
object sender, TextChangedEventArgs e)
 
  255             if (ItemsSource == null)
 
  258             updatingSelection = 
true;
 
  259             if (!IsDropDownOpen && !clearing)
 
  262                 var index = editableTextBox.CaretIndex;
 
  263                 IsDropDownOpen = 
true;
 
  264                 editableTextBox.CaretIndex = index;
 
  266             sort.Token = editableTextBox.Text;
 
  267             var cvs = CollectionViewSource.GetDefaultView(ItemsSource);
 
  269             if (listBox.Items.Count > 0 && !validating)
 
  271                 listBox.SelectedIndex = 0;
 
  273             updatingSelection = 
false;
 
  276         private void EditableTextBoxPreviewKeyDown(
object sender, KeyEventArgs e)
 
  278             if (listBox.Items.Count > 0)
 
  280                 updatingSelection = 
true;
 
  281                 if (e.Key == Key.Escape)
 
  283                     IsDropDownOpen = 
false;
 
  287                     listBox.SelectedIndex = Math.Max(listBox.SelectedIndex - 1, 0);
 
  288                     if (listBox.SelectedItem != null)
 
  289                         listBox.ScrollIntoView(listBox.SelectedItem);
 
  291                 if (e.Key == Key.Down)
 
  293                     listBox.SelectedIndex = Math.Min(listBox.SelectedIndex + 1, listBox.Items.Count - 1);
 
  294                     if (listBox.SelectedItem != null)
 
  295                         listBox.ScrollIntoView(listBox.SelectedItem);
 
  297                 if (e.Key == Key.PageUp)
 
  299                     var stackPanel = listBox.FindVisualChildOfType<VirtualizingStackPanel>();
 
  300                     if (stackPanel != null)
 
  302                         var 
count = stackPanel.Children.Count;
 
  303                         listBox.SelectedIndex = Math.Max(listBox.SelectedIndex - 
count, 0);
 
  307                         listBox.SelectedIndex = 0;
 
  309                     if (listBox.SelectedItem != null)
 
  310                         listBox.ScrollIntoView(listBox.SelectedItem);
 
  312                 if (e.Key == Key.PageDown)
 
  314                     var stackPanel = listBox.FindVisualChildOfType<VirtualizingStackPanel>();
 
  315                     if (stackPanel != null)
 
  317                         var 
count = stackPanel.Children.Count;
 
  318                         listBox.SelectedIndex = Math.Min(listBox.SelectedIndex + 
count, listBox.Items.Count - 1);
 
  322                         listBox.SelectedIndex = listBox.Items.Count - 1;
 
  324                     if (listBox.SelectedItem != null)
 
  325                         listBox.ScrollIntoView(listBox.SelectedItem);
 
  327                 if (e.Key == Key.Home)
 
  329                     listBox.SelectedIndex = 0;
 
  331                 if (e.Key == Key.End)
 
  333                     listBox.SelectedIndex = listBox.Items.Count - 1;
 
  335                 updatingSelection = 
false;
 
  339         private bool Filter(
object obj)
 
  341             if (editableTextBox == null)
 
  344             var filter = editableTextBox.Text;
 
  345             if (
string.IsNullOrWhiteSpace(filter))
 
  351             if (ItemsToExclude != null && ItemsToExclude.Cast<
object>().Contains(obj))
 
  354             var text = obj.ToString();
 
  355             return text.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) > -1 || MatchCamelCase(text);
 
  358         private bool MatchCamelCase(
string text)
 
  360             var camelCaseSplit = text.CamelCaseSplit();
 
  361             var filter = editableTextBox.Text.ToLowerInvariant();
 
  362             int currentFilterChar = 0;
 
  364             foreach (var word 
in camelCaseSplit)
 
  366                 int currentWordChar = 0;
 
  367                 while (currentFilterChar > 0)
 
  369                     if (
char.ToLower(word[currentWordChar]) == filter[currentFilterChar])
 
  374                 while (
char.ToLower(word[currentWordChar]) == filter[currentFilterChar])
 
  378                     if (currentFilterChar == filter.Length)
 
  381                     if (currentWordChar == word.Length)
 
  385             return currentFilterChar == filter.Length;
 
override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
An implementation of the TextBoxBase control that provides additional features such as a proper valid...
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
override void OnApplyTemplate()
int Compare(object x, object y)
override void OnSelectionChanged(SelectionChangedEventArgs e)
delegate void CancelRoutedEventHandler(object sender, CancelRoutedEventArgs e)