WPF中實現多選ComboBox控件


在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就實現了。代碼點擊這里下載。

感謝您的閱讀,如果您有其他實現方式,歡迎在評論區域點評,謝謝~

打賞

免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號  © 2018-2021 CODEPRJ.COM