在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就實作了。代碼點選
這裡下載下傳。
感謝您的閱讀,如果您有其他實作方式,歡迎在評論區域點評,謝謝~