/// <summary> /// AutoCompleteComboBox /// </summary> public class AutoCompleteComboBox : ComboBox { #region DependencyProperty public string WaterMark { get { return (string)GetValue(WaterMarkProperty); } set { SetValue(WaterMarkProperty, value); } } // Using a DependencyProperty as the backing store for WaterMark. This enables animation, styling, binding, etc... public static readonly DependencyProperty WaterMarkProperty = DependencyProperty.Register("WaterMark", typeof(string), typeof(AutoCompleteComboBox), new PropertyMetadata(null, new PropertyChangedCallback(OnWaterMarkChanged))); public bool? IsNull { get { return (bool?)GetValue(IsNullProperty); } set { SetValue(IsNullProperty, value); } } // Using a DependencyProperty as the backing store for IsNull. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsNullProperty = DependencyProperty.Register("IsNull", typeof(bool?), typeof(AutoCompleteComboBox), new PropertyMetadata(null)); public bool? SetFocuse { get { return (bool?)GetValue(SetFocuseProperty); } set { SetValue(SetFocuseProperty, value); } } // Using a DependencyProperty as the backing store for SetFocuse. This enables animation, styling, binding, etc... public static readonly DependencyProperty SetFocuseProperty = DependencyProperty.Register("SetFocuse", typeof(bool?), typeof(AutoCompleteComboBox), new PropertyMetadata(null, new PropertyChangedCallback(OnSetFocuseChanged))); public bool IsAllowNull { get { return (bool)GetValue(IsAllowNullProperty); } set { SetValue(IsAllowNullProperty, value); } } // Using a DependencyProperty as the backing store for IsAllowNull. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsAllowNullProperty = DependencyProperty.Register("IsAllowNull", typeof(bool), typeof(AutoCompleteComboBox), new PropertyMetadata(true, new PropertyChangedCallback(OnIsAllowNullChanged))); private static void OnIsAllowNullChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { } #endregion #region Event private static void OnWaterMarkChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { } private static void OnSetFocuseChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { AutoCompleteComboBox wm = obj as AutoCompleteComboBox; if (e.NewValue != null && wm.EditableTextBox != null) { if ((bool)e.NewValue == true && wm.EditableTextBox.IsFocused != true) { wm.EditableTextBox.Focus(); } } } public IList DataSource { get { return (IList)GetValue(DataSourceProperty); } set { SetValue(DataSourceProperty, value); } } // Using a DependencyProperty as the backing store for DataSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource", typeof(IList), typeof(AutoCompleteComboBox), new UIPropertyMetadata(null, new PropertyChangedCallback(OnDataSourceChanged))); private static void OnDataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AutoCompleteComboBox a = d as AutoCompleteComboBox; //if (a.IsAllowNull) //{ a.Items.Clear(); if (a.DataSource != null) { Type b = null; foreach (var item in a.DataSource) { if (b == null) { b = item.GetType(); object o = Activator.CreateInstance(b); //o.GetType().GetProperty(a.DisplayMemberPath).SetValue(o, "----Select----", null); a.Items.Add(o); } a.Items.Add(item); } } else { a.ItemsSource = null; } //} } protected override void OnDropDownOpened(EventArgs e) { base.OnDropDownOpened(e); if (this.HasItems) { this.Items[0].GetType().GetProperty(this.DisplayMemberPath).SetValue(this.Items[0], "----Select----", null); } } protected override void OnDropDownClosed(EventArgs e) { base.OnDropDownClosed(e); if (this.SelectedIndex == 0) { //this.SelectedItem = null; //this.SelectedItem = null; //this.Text = null; //this.SelectedValue = null; this.SelectedIndex = -1; } } public override void OnApplyTemplate() { base.OnApplyTemplate(); //load the text box control if (this.EditableTextBox != null && this.MyWaterMarkTextBlock != null) { if (SetFocuse == true) { if (!this.EditableTextBox.IsFocused) { this.EditableTextBox.Focus(); } } this.EditableTextBox.TextChanged += new TextChangedEventHandler(EditableTextBox_TextChanged); this.EditableTextBox.GotFocus += EditableTextBox_GotFocus; this.Loaded += AutoCompleteComboBox_Loaded; } } void AutoCompleteComboBox_Loaded(object sender, RoutedEventArgs e) { if (string.IsNullOrWhiteSpace(this.Text)) { this.MyWaterMarkTextBlock.Visibility = Visibility.Visible; //this.MyWaterMarkTextBlock.Text = WaterMark; this.IsNull = false; } else { this.MyWaterMarkTextBlock.Visibility = Visibility.Collapsed; //this.MyWaterMarkTextBlock.Text = WaterMark; this.IsNull = true; } try { //if (this.HasItems) //{ // this.Items[0].GetType().GetProperty(this.DisplayMemberPath).SetValue(this.Items[0], "----Select----", null); //} //if (!this.IsAllowNull) //{ // this.EditableTextBox.IsEnabled = false; //} } catch (Exception) { } } void EditableTextBox_GotFocus(object sender, RoutedEventArgs e) { if (this.MyWaterMarkTextBlock.Visibility == Visibility.Visible) { // this.Text = null; this.MyWaterMarkTextBlock.Visibility = Visibility.Collapsed; //this.MyWaterMarkTextBlock.Text = WaterMark; } this.IsDropDownOpen = true; } protected override void OnSelectionChanged(SelectionChangedEventArgs e) { base.OnSelectionChanged(e); if (this.SelectedIndex == 0) { this.SelectedIndex = -1; } } void EditableTextBox_TextChanged(object sender, TextChangedEventArgs e) { if (this.EditableTextBox.IsFocused && this.IsDropDownOpen == false) { this.IsDropDownOpen = true; } if (string.IsNullOrWhiteSpace(this.Text)) { if (!this.EditableTextBox.IsFocused) { this.MyWaterMarkTextBlock.Visibility = Visibility.Visible; // this.MyWaterMarkTextBlock.Text = WaterMark; } this.IsNull = false; } else { this.IsNull = true; this.MyWaterMarkTextBlock.Visibility = Visibility.Collapsed; // this.MyWaterMarkTextBlock.Text = WaterMark; } } void SimpleAutoCompleteComboBox_LostFocus(object sender, RoutedEventArgs e) { this.IsDropDownOpen = false; // to prevent misunderstanding that user has entered some information if (this.SelectedIndex == -1 || this.SelectedIndex == 0) { this.Text = null; this.SelectedItem = null; this.SelectedValue = null; this.MyWaterMarkTextBlock.Visibility = Visibility.Visible; this.IsNull = false; // this.MyWaterMarkTextBlock.Text = WaterMark; } // syncronize text else { this.Text = this.SelectedText; this.IsNull = true; } // release timer resources try { this.EditableTextBox.CaretIndex = 0; } catch { } } #endregion #region Construtor static AutoCompleteComboBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(typeof(AutoCompleteComboBox))); } public AutoCompleteComboBox() { this.StaysOpenOnEdit = true; this.IsEditable = true; this.IsTextSearchEnabled = true; this.LostFocus += SimpleAutoCompleteComboBox_LostFocus; this.IsAllowNull = true; } #endregion protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue) { base.OnItemsSourceChanged(oldValue, newValue); } #region property /// <summary> /// Gets the waterMark . /// </summary> protected TextBlock MyWaterMarkTextBlock { get { return base.GetTemplateChild("PART_MyWaterMarkTextBlock") as TextBlock; } } /// <summary> /// Gets the text box in charge of the editable portion of the combo box. /// </summary> protected TextBox EditableTextBox { get { return base.GetTemplateChild("PART_EditableTextBox") as TextBox; } } private string SelectedText { get { try { if (this.SelectedIndex == -1) return null; if (this.SelectedItem != null) { return this.SelectedItem.GetType().GetProperty(this.DisplayMemberPath).GetValue(this.SelectedItem, null).ToString(); } else { return null; } } catch (System.Exception) { return null; } } } #endregion }