当用户勾选下拉项时,下拉框中显示勾选的内容,并用逗号隔开,这里使用模板实现,在Combobox.ItemTemplate中使用Checkbox,参考代码如下:
<ComboBox Width="100"
IsEditable="True"
IsReadOnly="True"
Text="{Binding ItemText}"
ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}"
IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=ComboBox}}">
</CheckBox>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
如果你不设置CheckBox的宽度,这里点击到非CheckBox的区域的时候,ComboBox会显示选中的行,这显然不是我们想要的效果,简单的处理,即将ChecBox尽可能的占据ComboBoxItem的区域,所以我们在这里设置了它的宽度,并且将ComboBoxItem的Margin,Padding设置为0。
ComboBox的Text绑定了ItemText,IsChecked绑定了项的IsChecked属性,在属性改变时我们拼接ItemText的内容,参考代码如下:
private void Item_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsChecked")
{
string strItems = "";
foreach(var item in Items)
{
if (item.IsChecked)
{
strItems += item.Name+",";
}
}
ItemText = strItems.TrimEnd(',');
}
}
//mainwindow.xaml
<Window x:Class="ComboBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ComboBoxTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="ComboBoxItem">
<Setter Property="Margin" Value="0"></Setter>
<Setter Property="Padding" Value="0"></Setter>
</Style>
</Window.Resources>
<Grid>
<WrapPanel>
<ComboBox Width="100"
IsEditable="True"
IsReadOnly="True"
Text="{Binding ItemText}"
ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}"
IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=ComboBox}}">
</CheckBox>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</WrapPanel>
</Grid>
</Window>
//mainwindow.xaml.cs
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
namespace ComboBoxTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
public class Item: ObservableObject
{
private string m_Name;
public string Name
{
get { return m_Name; }
set { SetProperty(ref m_Name, value); }
}
private bool m_IsChecked;
public bool IsChecked
{
get
{
return m_IsChecked;
}
set
{
SetProperty(ref m_IsChecked, value);
}
}
}
public class MainWindowViewModel:ObservableObject
{
public MainWindowViewModel()
{
Item item = new Item();
item.Name = "123";
item.PropertyChanged += Item_PropertyChanged;
Items.Add(item);
Item item1 = new Item();
item1.Name = "456";
item1.PropertyChanged += Item_PropertyChanged;
Items.Add(item1);
Item item2 = new Item();
item2.Name = "789";
item2.PropertyChanged += Item_PropertyChanged;
Items.Add(item2);
}
private void Item_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsChecked")
{
string strItems = "";
foreach(var item in Items)
{
if (item.IsChecked)
{
strItems += item.Name+",";
}
}
ItemText = strItems.TrimEnd(',');
}
}
private ObservableCollection<Item> m_Items = new ObservableCollection<Item>();
public ObservableCollection<Item> Items
{
get
{
return m_Items;
}
set
{
SetProperty(ref m_Items,value);
}
}
private string m_ItemText;
public string ItemText
{
get
{
return m_ItemText;
}
set
{
SetProperty(ref m_ItemText,value);
}
}
}
}