在WPF中实现带CheckBox的ComboBox控件,让ComboBox控件能够支持多选。html
将ComboBox的ItemsSource属性Binding到一个Book的集合,post
public class Book { public string Name { get; set; } }
<ComboBox ItemsSource="{Binding Path=Books}"> <ComboBox.ItemTemplate> <DataTemplate DataType="{x:Type local:Book}"> <StackPanel> <TextBlock Text="{Binding Name}" /> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
显示效果以下:
ui
为了让ComboBox支持CheckBox,和上面代码同样,修改ComboBox的DataTemplate,CheckBox的选中/非选中状态须要Binding到一个Bool型的Property上面。可是这个Property并非Book的一个属性,因此新建一个BookEx类,增长一个IsChecked属性spa
public class BookEx : ObservableObject { public Book Book { get; private set; } private bool _isChecked; public bool IsChecked { get { return _isChecked; } set { if(_isChecked != value) { _isChecked = value; RaisePropertyChanged("IsChecked"); } } } public BookEx(Book book) { Book = book; } }
将ComboBox的ItemsSource属性Binding到BookEx集合上,下面修改ComboBox的DataTemplate:
code
此时已经能够实现多选了,可是当选择相应的条目后,在ComboBox的Text区域并不显示。下面来解决这个问题。实现方式是将选中的Book的Name属性集合Binding到ComboBox的Text属性上面。对ViewModel作一些改造,增长一个SelectedText属性,用来显示选中的条目Name集合htm
public ObservableCollection<BookEx> BookExs { get { if(_books == null) { _books = new ObservableCollection<BookEx>(); _books.CollectionChanged += (sender, e) => { if(e.OldItems != null) { foreach (BookEx bookEx in e.OldItems) { bookEx.PropertyChanged -= ItemPropertyChanged; } } if(e.NewItems != null) { foreach (BookEx bookEx in e.NewItems) { bookEx.PropertyChanged += ItemPropertyChanged; } } }; } return _books; } } private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) { if(e.PropertyName == "IsChecked") { BookEx bookEx = sender as BookEx; if(bookEx != null) { IEnumerable<BookEx> bookExs = BookExs.Where(b => b.IsChecked == true); StringBuilder builder = new StringBuilder(); foreach (BookEx item in bookExs) { builder.Append(item.Book.Name + " "); } SelectedText = builder == null ? string.Empty : builder.ToString(); } } }
最后一个注意点,修改ComboBox的IsEditable="True",只有这样才能接收Text的Binding。blog
<ComboBox Text="{Binding SelectedText}" IsEditable="True" ItemsSource="{Binding Path=BookExs}"> <ComboBox.ItemTemplate> <DataTemplate DataType="{x:Type local:BookEx}"> <StackPanel Orientation="Horizontal"> <CheckBox IsChecked="{Binding IsChecked}" /> <TextBlock Text="{Binding Book.Name}" /> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
实现的效果以下:
ip
就这样一个能够多选的ComboBox就实现了。代码点击这里下载。get
感谢您的阅读,若是您有其余实现方式,欢迎在评论区域点评,谢谢~string