WPF ComboBox多选下拉框,支持MVVM绑定选中项

5 篇文章 1 订阅

不想自己撸代码的可以使用免费的XiaFControl控件库,在nuget包中搜索XiaFControl。各种控件都有哦!
示例代码:
github示例demo代码https://github.com/LiuliuMao/XiaFControl
gitee示例demo代码https://gitee.com/lm961031/xia-fcontrol
QQ交流群:371769310
多选下拉框

下面都是源码,可以直接拿去用

 /// <summary>
    /// MultiSelectComboBox.xaml 的交互逻辑
    /// </summary>
    public partial class MultiSelectComboBox : UserControl
    {
        private ObservableCollection<Node> _nodeList;

        private void DisplayInControl()
        {
            _nodeList.Clear();
            if (this.ItemsSource.Count > 0)
                _nodeList.Add(new Node("All"));
            foreach (KeyValuePair<string, object> keyValue in this.ItemsSource)
            {
                Node node = new Node(keyValue.Key);
                _nodeList.Add(node);
            }
            MultiSelectCombo.ItemsSource = _nodeList;
        }
        private void CheckBox_Click(object sender, RoutedEventArgs e)
        {
            CheckBox clickedBox = (CheckBox)sender;

            if (clickedBox.Content == "All")
            {
                if (clickedBox.IsChecked.Value)
                {
                    foreach (Node node in _nodeList)
                    {
                        node.IsSelected = true;
                    }
                }
                else
                {
                    foreach (Node node in _nodeList)
                    {
                        node.IsSelected = false;
                    }
                }
            }
            else
            {
                int _selectedCount = 0;
                foreach (Node s in _nodeList)
                {
                    if (s.IsSelected && s.Title != "All")
                        _selectedCount++;
                }
                if (_selectedCount == _nodeList.Count - 1)
                    _nodeList.FirstOrDefault(i => i.Title == "All").IsSelected = true;
                else
                    _nodeList.FirstOrDefault(i => i.Title == "All").IsSelected = false;
            }
            SetSelectedItems();
        }
        private void SetSelectedItems()
        {
            if (SelectedItems == null)
                SelectedItems = new Dictionary<string, object>();
            SelectedItems.Clear();
            foreach (Node node in _nodeList)
            {
                if (node.IsSelected && node.Title != "All")
                {
                    if (this.ItemsSource.Count > 0)

                        SelectedItems.Add(node.Title, this.ItemsSource[node.Title]);
                }
            }
        }
        private void SelectNodes()
        {
            foreach (KeyValuePair<string, object> keyValue in SelectedItems)
            {
                Node node = _nodeList.FirstOrDefault(i => i.Title == keyValue.Key);
                if (node != null)
                    node.IsSelected = true;
            }
        }
        private void SetText()
        {
            if (this.SelectedItems != null)
            {
                StringBuilder displayText = new StringBuilder();
                foreach (Node s in _nodeList)
                {
                    if (s.IsSelected == true && s.Title == "All")
                    {
                        displayText = new StringBuilder();
                        displayText.Append("All");
                        break;
                    }
                    else if (s.IsSelected == true && s.Title != "All")
                    {
                        displayText.Append(s.Title);
                        displayText.Append(',');
                    }
                }
                this.Text = displayText.ToString().TrimEnd(new char[] { ',' });
            }
            // set DefaultText if nothing else selected
            if (string.IsNullOrEmpty(this.Text))
            {
                this.Text = this.DefaultText;
            }
        }
        public MultiSelectComboBox()
        {
            InitializeComponent();
            _nodeList = new ObservableCollection<Node>();
        }

        public static readonly DependencyProperty SelectedItemsProperty =
         DependencyProperty.Register
         ("SelectedItems", typeof(Dictionary<string, object>),
         typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(null,
         new PropertyChangedCallback
         (MultiSelectComboBox.OnSelectedItemsChanged)));

        private static void OnSelectedItemsChanged
        (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MultiSelectComboBox control = (MultiSelectComboBox)d;
            control.SelectNodes();
            control.SetText();
        }

        public static readonly DependencyProperty ItemsSourceProperty =
   DependencyProperty.Register("ItemsSource", typeof(Dictionary<string,
   object>), typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(null,
   new PropertyChangedCallback(MultiSelectComboBox.OnItemsSourceChanged)));
        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MultiSelectComboBox control = (MultiSelectComboBox)d;
            control.DisplayInControl();
        }
        //public static readonly DependencyProperty ItemsSourceProperty =
        //    DependencyProperty.Register("ItemsSource", typeof(Dictionary<string, object>),
        //    typeof(MultiSelectComboBox), new UIPropertyMetadata(string.Empty));

     

        public static readonly DependencyProperty TextProperty =
           DependencyProperty.Register("Text",
           typeof(string), typeof(MultiSelectComboBox),
           new UIPropertyMetadata(string.Empty));

        public static readonly DependencyProperty DefaultTextProperty =
            DependencyProperty.Register("DefaultText", typeof(string),
            typeof(MultiSelectComboBox), new UIPropertyMetadata(string.Empty));

        public Dictionary<string, object> ItemsSource
        {
            get
            {
                return (Dictionary<string,
          object>)GetValue(ItemsSourceProperty);
            }
            set
            {
                SetValue(ItemsSourceProperty, value);
            }
        }

        public Dictionary<string, object> SelectedItems
        {
            get
            {
                return (Dictionary<string,
          object>)GetValue(SelectedItemsProperty);
            }
            set
            {
                SetValue(SelectedItemsProperty, value);
            }
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public string DefaultText
        {
            get { return (string)GetValue(DefaultTextProperty); }
            set { SetValue(DefaultTextProperty, value); }
        }
    }
    public class Node : INotifyPropertyChanged
    {
        private string _title;
        private bool _isSelected;
        #region ctor
        public Node(string title)
        {
            Title = title;
        }
        #endregion

        #region Properties
        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value;
                NotifyPropertyChanged("Title");
            }
        }
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                _isSelected = value;
                NotifyPropertyChanged("IsSelected");
            }
        }
        #endregion

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

Text属性是用来显示多选项的值,在没有选中项的时候Text的值等于DefaultText属性的值,可以在使用时,将DefaultText赋值请选择之类的提示语。

xaml界面样式如下:

 <ComboBox
        x:Name="MultiSelectCombo"  
        SnapsToDevicePixels="True"
        OverridesDefaultStyle="True"
        ScrollViewer.HorizontalScrollBarVisibility="Auto"
        ScrollViewer.VerticalScrollBarVisibility="Auto"
        ScrollViewer.CanContentScroll="True"
        IsSynchronizedWithCurrentItem="True">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Title}"
      IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"
      Tag="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"
      Click="CheckBox_Click" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
            <ComboBox.Template>
                <ControlTemplate TargetType="ComboBox">
                    <Grid >
                        <ToggleButton 
                        x:Name="ToggleButton" 
                       Grid.Column="2" IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,
                       RelativeSource={RelativeSource TemplatedParent}}"
                        Focusable="false"                           
                        ClickMode="Press" HorizontalContentAlignment="Left" >
                            <ToggleButton.Template>
                                <ControlTemplate>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="18"/>
                                        </Grid.ColumnDefinitions>
                                        <Border
                  x:Name="Border" 
                  Grid.ColumnSpan="2"
                  CornerRadius="2"
                  Background="White"
                  BorderBrush="Black"
                  BorderThickness="1,1,1,1" />
                                        <Border 
                    x:Name="BorderComp" 
                  Grid.Column="0"
                  CornerRadius="2" 
                  Margin="1" 
                 Background="White"
                  BorderBrush="Black"
                  BorderThickness="0,0,0,0" >
                                            <TextBlock Text="
                                        {Binding Path=Text,RelativeSource=
                                        {RelativeSource Mode=FindAncestor, 
                                        AncestorType=UserControl}}" 
                                               Background="White" 
                                               Padding="3" />
                                        </Border>
                                        <Path 
                  x:Name="Arrow"
                  Grid.Column="1"     
                  Fill="Black"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"
                  Data="M 0 0 L 4 4 L 8 0 Z"/>
                                    </Grid>
                                </ControlTemplate>
                            </ToggleButton.Template>
                        </ToggleButton>
                        <Popup IsOpen="{TemplateBinding IsDropDownOpen}"
PopupAnimation="Slide"
            Name="Popup"
            Placement="Bottom"                        
            AllowsTransparency="True" MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
            Focusable="False" >
                            <Grid 
                      Name="DropDown"
                      SnapsToDevicePixels="True" >
                                <Border 
                        x:Name="DropDownBorder"
                       BorderThickness="1" Background="White"
                                 BorderBrush="Black"/>
                                <ScrollViewer Margin="4,6,4,6" 
                    SnapsToDevicePixels="True" 
                    DataContext="{Binding}">
                                    <StackPanel IsItemsHost="True" 
                        KeyboardNavigation.DirectionalNavigation=
                        "Contained" />
                                </ScrollViewer>
                            </Grid>
                        </Popup>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="HasItems" Value="false">
                            <Setter TargetName="DropDownBorder" 
        Property="MinHeight" Value="95"/>
                        </Trigger>
                        <Trigger SourceName="Popup" 
Property="Popup.AllowsTransparency" Value="true">
                            <Setter TargetName="DropDownBorder" 
    Property="CornerRadius"   Value="4"/>
                            <Setter TargetName="DropDownBorder" 
    Property="Margin" Value="0,2,0,0"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </ComboBox.Template>
        </ComboBox>

使用时调用:

   <Grid>
        <wpfcon:MultiSelectComboBox SelectedItems="{Binding SelectedItems}" ItemsSource="{Binding Items}"/>
      
    </Grid>
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
WPF中实现多选下拉框可以使用ComboBox和ListBox结合实现,然后使用MVVM模式来实现数据绑定。以下是实现的步骤: 1. 定义一个数据模型,用于存储下拉框的选数据和选中状态。 ```csharp public class MultiSelectItem<T> { public T Item { get; set; } public bool IsSelected { get; set; } } ``` 2. 在ViewModel中,定义一个集合用于存储选数据,并且提供一个属性用于绑定ComboBox中的ItemsSource,以及提供一个属性用于绑定到ListBox中的ItemsSource。 ```csharp public class MainViewModel : INotifyPropertyChanged { private List<MultiSelectItem<string>> _items; public MainViewModel() { _items = new List<MultiSelectItem<string>>() { new MultiSelectItem<string>() {Item = "Item 1", IsSelected = false}, new MultiSelectItem<string>() {Item = "Item 2", IsSelected = false}, new MultiSelectItem<string>() {Item = "Item 3", IsSelected = false}, new MultiSelectItem<string>() {Item = "Item 4", IsSelected = false}, new MultiSelectItem<string>() {Item = "Item 5", IsSelected = false}, }; } public List<MultiSelectItem<string>> Items { get { return _items; } set { _items = value; OnPropertyChanged(nameof(Items)); } } public IEnumerable<string> SelectedItems { get { return _items.Where(x => x.IsSelected).Select(x => x.Item); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ``` 3. 在View中,使用ComboBox和ListBox来实现多选下拉框ComboBox用于展示选中的选,ListBox用于展示所有的选。 ```xml <ComboBox ItemsSource="{Binding SelectedItems}"> <ComboBox.Style> <Style TargetType="ComboBox"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ComboBox"> <StackPanel Orientation="Vertical"> <TextBlock Text="Selected Items:" /> <ItemsControl ItemsSource="{Binding SelectedItems}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </ComboBox.Style> </ComboBox> <ListBox ItemsSource="{Binding Items}"> <ListBox.ItemTemplate> <DataTemplate> <CheckBox Content="{Binding Item}" IsChecked="{Binding IsSelected}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> ``` 以上就是使用MVVM模式实现WPF多选下拉框的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值