Loading

带搜索的ComboBox

带搜索的ComboBox就是给ComboBox一个依赖属性的ItemSource,然后通过数据源中是否包含要查询的值,重新给ComboBox绑定数据源。

public class EditComboBox : ComboBox
    {
        private bool t = true;//首次获取焦点标志位
        private ObservableCollection<object> bindingList = new ObservableCollection<object>();//数据源绑定List
        private string editText = "";//编辑文本内容

        /// <summary>
        /// 注册依赖事件
        /// </summary>
        public static readonly DependencyProperty ItemsSourcePropertyNew = DependencyProperty.Register("MyItemsSource", typeof(IEnumerable), typeof(EditComboBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(ValueChanged)));
        /// <summary>
        /// 数据源改变,添加数据源到绑定数据源
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            EditComboBox ecb = d as EditComboBox;
            ecb.bindingList.Clear();
            //遍历循环操作
            foreach (var item in ecb.MyItemsSource)
            {
                ecb.bindingList.Add(item);
            }
        }
        /// <summary>
        /// 设置或获取ComboBox的数据源
        /// </summary>
        public IEnumerable MyItemsSource
        {
            get
            {
                return (IEnumerable)GetValue(ItemsSourcePropertyNew);
            }

            set
            {
                if (value == null)
                    ClearValue(ItemsSourcePropertyNew);
                else
                    SetValue(ItemsSourcePropertyNew, value);
            }
        }
        /// <summary>
        /// 重写初始化
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            this.IsEditable = true;
            this.IsTextSearchEnabled = false;
            this.ItemsSource = bindingList;
        }
        /// <summary>
        /// 下拉框获取焦点,首次搜索文本编辑框
        /// </summary>
        /// <param name="e"></param>
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            if (t)
                FindTextBox(this);
            else
                t = false;
        }
        /// <summary>
        /// 搜索编辑文本框,添加文本改变事件
        /// </summary>
        /// <param name="obj"></param>
        private void FindTextBox(DependencyObject obj)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child!=null && child is TextBox)
                {
                    //注册文本改变事件
                    (child as TextBox).TextChanged += EditComboBox_TextChanged;
                }
                else
                {
                    FindTextBox(child);
                }
            }
        }
        /// <summary>
        /// 文本改变,动态控制下拉条数据源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EditComboBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox tb = sender as TextBox;
            if(tb.IsFocused)
            {
                this.IsDropDownOpen = true;
                if (editText == this.Text)
                    return;
                editText = this.Text;
                SetList(editText);
            }
        }
        /// <summary>
        /// 组合框关闭,数据源恢复
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDropDownClosed(EventArgs e)
        {
            base.OnDropDownClosed(e);
            if (MyItemsSource == null)
                return;
            foreach (var item in MyItemsSource)
            {
                if (!bindingList.Contains(item))
                    bindingList.Add(item);
            }
        }
        /// <summary>
        /// 过滤符合条件的数据项,添加到数据源项中
        /// </summary>
        /// <param name="txt"></param>
        private void SetList(string txt)
        {
            try
            {
                string temp1 = "";
                string temp2 = "";
                if (MyItemsSource == null)
                    return;
                foreach (var item in MyItemsSource)
                {
                    temp1 = item.GetType().GetProperty(this.DisplayMemberPath).GetValue(item, null).ToString();
                    if (string.IsNullOrEmpty(this.SelectedValuePath))
                    {
                        temp2 = "";
                    }
                    else
                    {
                        temp2 = item.GetType().GetProperty(this.SelectedValuePath).GetValue(item, null).ToString();
                    }
                    if(temp1.Contains(txt)||temp2.StartsWith(txt))
                    {
                        if (!bindingList.Contains(item))
                            bindingList.Add(item);
                    }
                    else if (bindingList.Contains(item))
                    {
                        bindingList.Remove(item);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

调用方法就是将数据源绑定到MyItemsSource上,剩下的就和原有的ComboBox用法一样了。

<local:EditComboBox MyItemsSource="{Binding ProList,Mode=TwoWay}" SelectedItem="{Binding Selpro,Mode=TwoWay}" SelectedValuePath="Id" DisplayMemberPath="Name"/>

效果演示

posted @ 2016-09-21 09:40  眾尋  阅读(1609)  评论(1编辑  收藏  举报