1. 程式人生 > >多選Combobox的實現(適合MVVM模式)

多選Combobox的實現(適合MVVM模式)

MVVM沒有.cs後臺邏輯,一般依靠command驅動邏輯及通過binding(vm層的屬性)來顯示前端

我的資料類Student有三個屬性int StuId ,string StuName ,bool isChecked。

首先第一步建立一個UserControl,裡面放一個ComboBox

  <ComboBox x:Name="cb" Width="150" Height="25" ItemsSource="{Binding StudentList}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox Click="CheckBox_Click" IsChecked="{Binding IsChecked,Mode=TwoWay}"/>
                        <TextBlock Text="{Binding StuName}"/>
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

ComboBox 的樣式改造如前篇非MvvM模式下的改造一樣,只要將template中ContentPresenter的Content="{TemplateBinding SelectionBoxItem}"改成Content="{TemplateBinding Tag}"即可。

然後在UserControl.cs里加一個依賴屬性

public List<Student> SelectedItems1
        {
            get { return (List<Student>)GetValue(SelectedItems1Property); }
            set { SetValue(SelectedItems1Property, value); }
        }

        public static readonly DependencyProperty SelectedItems1Property =
            DependencyProperty.Register("SelectedItems1", typeof(List<Student>), typeof(ComboboxEx),new PropertyMetadata(null,new PropertyChangedCallback(OnSelectedChangeCallBack)));

        private static void OnSelectedChangeCallBack(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            MessageBox.Show("Success");
        }

這裡在回撥函式中做了個彈出框的處理,用來判斷屬性繫結是否成功。

勾選框的邏輯處理:

private void CheckBox_Click(object sender, RoutedEventArgs e)
        {
            var items = this.cb.ItemsSource ;

            if (items != null )
            {
                SelectedStr=string.Empty;
                foreach (Student item in items)
                {
                    if (item.IsChecked == true)
                    {
                        SelectedStr = string.Format("{0}{1};", SelectedStr, item.StuName);
                    }
                }

                this.cb.Tag = SelectedStr;
            }
        }

第二步,建立ViewModel層

裡面建立兩個屬性,一個用來建立資料來源集合,一個用來存放勾選的集合

public ObservableCollection<Student> StudentList{get;set;}

        private List<Student> _SelectedItems;

        public List<Student> SelectedItems
        {
            get { return _SelectedItems; }
            set
            {
                if (PropertyChanged != null)
                {
                    _SelectedItems = value;
                    this.PropertyChanged(this, new PropertyChangedEventArgs("SelectedItems"));
                }  
            }
        }

建立一個command及一個遍歷方法

public ICommand CheckItemsChangedCommand { get; set; }

public void UpdataSelecteditems()
        {
            List<Student> slist = new List<Student>();
            foreach (var item in StudentList)
            {
                if (item.IsChecked == true)
                {
                    slist.Add(item);
                }
            }
            SelectedItems = slist;
        }

在ViewModel建構函式中繫結資料集合,例項化Command;

public ComboboxViewModel()
        {
            SelectedItems = new List<Student>();

            StudentList = new ObservableCollection<Student>()
            {
                new Student(){StuId=1,StuName="aaa"},
                new Student(){StuId=2,StuName="bbb"},
                new Student(){StuId=3,StuName="ccc"},
                new Student(){StuId=3,StuName="ddd"},
                new Student(){StuId=3,StuName="eee"}
            };

            CheckItemsChangedCommand = new ActionCommand(this.UpdataSelecteditems);

                }

最後一步完成部件的組裝

<StackPanel>
            <UserControls:ComboboxEx x:Name="cb" SelectedItems1="{Binding SelectedItems}"></UserControls:ComboboxEx>
            <Button HorizontalAlignment="Center" Content="Click" Command="{Binding CheckItemsChangedCommand}"/>
        </StackPanel>

後臺加 this.DataContext = new ComboboxViewModel();

(PS:當在Selecte ComboboxItem而非Check的時候,combobox head會顯示checkbox。這裡要重現ComboboxItem的onMouseLeftUp事件,裡面改成e.handle =true即可)