WPF Combox实现下拉多选,可选中多个值
阅读原文时间:2021年08月11日阅读:1

自定义多选MultiCombox,可以实现下拉列表多选

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace MES.Plugin.Report.Controls
{
public class MultiComboBox : ComboBox
{
static MultiComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiComboBox), new FrameworkPropertyMetadata(typeof(MultiComboBox)));
}

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
    {  
        d.SetValue(e.Property, e.NewValue);  
    }

    /// <summary>  
    /// 选中项列表  
    /// </summary>  
    public ObservableCollection<MultiCbxBaseData> ChekedItems = new ObservableCollection<MultiCbxBaseData>();

    /// <summary>  
    /// ListBox竖向列表  
    /// </summary>  
    private ListBox \_ListBoxV;

    /// <summary>  
    /// ListBox横向列表  
    /// </summary>  
    private ListBox \_ListBoxH;

    public override void OnApplyTemplate()  
    {  
        base.OnApplyTemplate();  
        \_ListBoxV = Template.FindName("PART\_ListBox", this) as ListBox;  
        \_ListBoxH = Template.FindName("PART\_ListBoxChk", this) as ListBox;  
        \_ListBoxH.ItemsSource = ChekedItems;  
        \_ListBoxV.SelectionChanged += \_ListBoxV\_SelectionChanged;  
        \_ListBoxH.SelectionChanged += \_ListBoxH\_SelectionChanged;

        if (ItemsSource != null)  
        {  
            foreach (var item in ItemsSource)  
            {  
                MultiCbxBaseData bdc = item as MultiCbxBaseData;  
                if (bdc.IsCheck)  
                {  
                    \_ListBoxV.SelectedItems.Add(bdc);  
                }  
            }  
        }  
    }

    private void \_ListBoxH\_SelectionChanged(object sender, SelectionChangedEventArgs e)  
    {  
        foreach (var item in e.RemovedItems)  
        {  
            MultiCbxBaseData datachk = item as MultiCbxBaseData;

            for (int i = 0; i < \_ListBoxV.SelectedItems.Count; i++)  
            {  
                MultiCbxBaseData datachklist = \_ListBoxV.SelectedItems\[i\] as MultiCbxBaseData;  
                if (datachklist.ID == datachk.ID)  
                {  
                    \_ListBoxV.SelectedItems.Remove(\_ListBoxV.SelectedItems\[i\]);  
                }  
            }  
        }  
    }

    void \_ListBoxV\_SelectionChanged(object sender, SelectionChangedEventArgs e)  
    {  
        foreach (var item in e.AddedItems)  
        {  
            MultiCbxBaseData datachk = item as MultiCbxBaseData;  
            datachk.IsCheck = true;  
            if (ChekedItems.IndexOf(datachk) < 0)  
            {  
                ChekedItems.Add(datachk);  
            }  
        }

        foreach (var item in e.RemovedItems)  
        {  
            MultiCbxBaseData datachk = item as MultiCbxBaseData;  
            datachk.IsCheck = false;  
            ChekedItems.Remove(datachk);  
        }  
    }  
    public class MultiCbxBaseData  
    {  
        private int \_id;  
        public int ID  
        {  
            get { return \_id; }  
            set { \_id = value; }  
        }

        private string \_viewName;  
        public string ViewName  
        {  
            get { return \_viewName; }  
            set  
            {  
                \_viewName = value;  
            }  
        }

        private bool \_isCheck;  
        /// <summary>  
        /// 是否选中  
        /// </summary>  
        public bool IsCheck  
        {  
            get { return \_isCheck; }  
            set { \_isCheck = value; }  
        }  
    }  
}  

}

Style: ComboBox.xmal










<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">  
    <Grid Height="25" HorizontalAlignment="Stretch">  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="\*"/>  
            <ColumnDefinition Width="30"/>  
        </Grid.ColumnDefinitions>  
        <Border  Background="White" Grid.ColumnSpan="2" Opacity="0"/>  
        <Path x:Name="Arrow" Grid.Column="1"   Data="M 0 0  6 6 12 0 Z" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" Fill="#999" />  
    </Grid>  
    <ControlTemplate.Triggers>  
        <Trigger Property="IsChecked" Value="true">  
            <Setter TargetName="Arrow" Property="RenderTransform">  
                <Setter.Value>  
                    <RotateTransform   CenterX="6" CenterY="3" Angle="180"></RotateTransform>  
                </Setter.Value>  
            </Setter>  
            <Setter TargetName="Arrow" Property="Margin" Value="0 0 0 2"/>  
        </Trigger>  
    </ControlTemplate.Triggers>  
</ControlTemplate>

<!--MultiComboBox普通样式-->  
<Style  TargetType="{x:Type controls:MultiComboBox}">  
    <Setter Property="Width" Value="200" />  
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />  
    <Setter Property="VerticalContentAlignment" Value="Center" />  
    <Setter Property="SnapsToDevicePixels" Value="True" />  
    <Setter Property="MaxDropDownHeight" Value="400" />  
    <Setter Property="Template">  
        <Setter.Value>  
            <ControlTemplate TargetType="{x:Type controls:MultiComboBox}">  
                <Grid>  
                    <Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"  Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderBrush="#eaeaea" BorderThickness="1"  >  
                        <Grid x:Name="PART\_Root">

                            <Grid x:Name="PART\_InnerGrid" Margin="0">  
                                <Grid.ColumnDefinitions>  
                                    <ColumnDefinition Width="\*" />  
                                    <ColumnDefinition Width="0.3\*" MaxWidth="30" />  
                                </Grid.ColumnDefinitions>  
                                <ListBox x:Name="PART\_ListBoxChk" Background="#2d2f3e"  SelectionMode="Multiple" BorderThickness="0" ScrollViewer.VerticalScrollBarVisibility="Disabled">  
                                    <ListBox.ItemsPanel>  
                                        <ItemsPanelTemplate>  
                                            <VirtualizingStackPanel Orientation="Horizontal" VirtualizingStackPanel.IsVirtualizing="True" />  
                                        </ItemsPanelTemplate>  
                                    </ListBox.ItemsPanel>  
                                    <ListBox.ItemContainerStyle>  
                                        <Style TargetType="ListBoxItem">  
                                            <Setter Property="BorderThickness" Value="0"/>  
                                            <Setter Property="IsSelected" Value="True"/>  
                                            <Setter Property="Template">  
                                                <Setter.Value>  
                                                    <ControlTemplate TargetType="ListBoxItem">  
                                                        <CheckBox BorderThickness="0" Background="#2d2f3e" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"  Content="{Binding ViewName}" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>  
                                                    </ControlTemplate>  
                                                </Setter.Value>  
                                            </Setter>  
                                        </Style>  
                                    </ListBox.ItemContainerStyle>  
                                </ListBox>

                                <!--下拉按钮-->  
                                <ToggleButton x:Name="PART\_DropDownToggle" IsTabStop="False"  
                                     IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"  
                                     Grid.Column="1" Template="{StaticResource ComboBoxToggleButton}" />  
                            </Grid>  
                        </Grid>  
                    </Border>  
                    <!--弹出多选列表-->  
                    <Popup x:Name="PART\_Popup" AllowsTransparency="True"  Focusable="False" StaysOpen="False"  
                           IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"  
                           PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">  
                        <Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}"  MaxHeight="{Binding MaxDropDownHeight, RelativeSource={RelativeSource TemplatedParent}}" >  
                            <ListBox x:Name="PART\_ListBox" SelectionMode="Multiple" BorderThickness="1 0 1 1" Background="White" ItemsSource="{Binding ItemsSource,RelativeSource={RelativeSource TemplatedParent}}"  
                                         MaxHeight="{TemplateBinding MaxDropDownHeight}" BorderBrush="#eaeaea"  >  
                                <ListBox.ItemContainerStyle>  
                                    <Style  TargetType="ListBoxItem">  
                                        <Setter Property="Template">  
                                            <Setter.Value>  
                                                <ControlTemplate TargetType="{x:Type ListBoxItem}" >  
                                                    <Grid  Height="22">  
                                                        <Border x:Name="bg" BorderBrush="#eaeaea" BorderThickness="0"/>  
                                                        <ContentPresenter x:Name="content"  />  
                                                        <Border Background="White"  Opacity="0"/>  
                                                    </Grid>  
                                                    <ControlTemplate.Triggers>  
                                                        <Trigger Property="IsSelected" Value="True">  
                                                            <Setter  TargetName="bg"  Property="Background" Value="#ADD6FF" />  
                                                        </Trigger>  
                                                        <MultiTrigger>  
                                                            <MultiTrigger.Conditions>  
                                                                <Condition Property="IsMouseOver" Value="true" />  
                                                                <Condition Property="IsSelected" Value="false"/>  
                                                            </MultiTrigger.Conditions>  
                                                            <Setter TargetName="bg" Property="Background" Value="#009BDB" />  
                                                            <Setter TargetName="bg" Property="Opacity" Value="0.7"/>  
                                                            <Setter   Property="Foreground" Value="White" />  
                                                        </MultiTrigger>  
                                                        <Trigger Property="IsEnabled" Value="False">  
                                                            <Setter TargetName="bg" Property="Opacity" Value="0.3" />  
                                                            <Setter   Property="Foreground" Value="Gray" />  
                                                        </Trigger>  
                                                    </ControlTemplate.Triggers>  
                                                </ControlTemplate>  
                                            </Setter.Value>  
                                        </Setter>  
                                    </Style>  
                                </ListBox.ItemContainerStyle>  
                                <ListBox.ItemTemplate>  
                                    <DataTemplate>  
                                        <Grid>  
                                            <CheckBox x:Name="chk" Visibility="Hidden"  IsChecked="{Binding IsCheck,Mode=TwoWay}" VerticalAlignment="Center"/>  
                                            <CheckBox VerticalAlignment="Center"  Foreground="{Binding Foreground,RelativeSource={RelativeSource AncestorType=ListBoxItem}}" IsChecked="{Binding  RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected,Mode=TwoWay}"  Content="{Binding Path=ViewName}" />  
                                        </Grid>  
                                        <DataTemplate.Triggers>  
                                            <DataTrigger   Binding="{Binding  RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="true">  
                                                <Setter  TargetName="chk"  Property="IsChecked" Value="true"/>  
                                            </DataTrigger>  
                                            <DataTrigger   Binding="{Binding  RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="false">  
                                                <Setter     TargetName="chk" Property="IsChecked" Value="false"/>  
                                            </DataTrigger>  
                                        </DataTemplate.Triggers>  
                                    </DataTemplate>  
                                </ListBox.ItemTemplate>  
                            </ListBox>  
                        </Grid>  
                    </Popup>  
                </Grid>

            </ControlTemplate>  
        </Setter.Value>  
    </Setter>  
</Style>  

前端使用:

1.引用Style资源,在前端引用上面建好的ComboBox.xmal 样式

 

2.控件使用

3.MutilComboBox 数据源绑定,刷新数据源

ObservableCollection MultiComboBoxListData = new ObservableCollection();
for (int i = 0; i<LstLine.Count; i++)
{
SFC_WORKCENTER workcenter = LstLine[i];
if (string.IsNullOrEmpty(workcenter.ID)) continue;
if (workcenter.WORKCENTER_NAME.Contains("过塑")) {
MultiComboBoxListData.Add(new Controls.MultiComboBox.MultiCbxBaseData()
{
ID = i,
ViewName = workcenter.WORKCENTER_CODE,
//LineName = workcenter.WORKCENTER_NAME,
IsCheck = false
});
}
else
{
MultiComboBoxListData.Add(new Controls.MultiComboBox.MultiCbxBaseData()
{
ID = i,
ViewName = workcenter.WORKCENTER_CODE,
//LineName = workcenter.WORKCENTER_NAME,
IsCheck = true
});
}
}
plugin.MultiCmb.ItemsSource = MultiComboBoxListData;
       plugin.MultiCmb.OnApplyTemplate();