在WPF中實現帶CheckBox的ComboBox控件,讓ComboBox控件可以支持多選。
將ComboBox的ItemsSource屬性Binding到一個Book的集合,
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>
顯示效果如下:
為了讓ComboBox支持CheckBox,和上面代碼一樣,修改ComboBox的DataTemplate,CheckBox的選中/非選中狀態需要Binding到一個Bool型的Property上面。但是這個Property並不是Book的一個屬性,所以新建一個BookEx類,增加一個IsChecked屬性
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:
此時已經可以實現多選了,但是當選擇相應的條目后,在ComboBox的Text區域並不顯示。下面來解決這個問題。實現方式是將選中的Book的Name屬性集合Binding到ComboBox的Text屬性上面。對ViewModel做一些改造,增加一個SelectedText屬性,用來顯示選中的條目Name集合
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。
<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>
實現的效果如下:
就這樣一個可以多選的ComboBox就實現了。代碼點擊這里下載。
感謝您的閱讀,如果您有其他實現方式,歡迎在評論區域點評,謝謝~