由于 xceed wpf 工具包对我不起作用,我尝试使用 C# 和 WPF 创建自定义多选组合框,方法是使用复选框填充组合框并设置其宽度属性,以便下拉列表不会关闭,并使用 Content 属性标签。
鉴于选择是多个而不是单个项目,我想将组合框的文本设置为“X selected”之类的内容,其中 X 表示组合框中选中的项目数。
在到达确定检查了多少项目的阶段之前,我尝试使用事件处理程序(CheckBoxClosed 和 SelectionChanged)以编程方式手动设置组合框的文本,但复选框的文本仍为空。
该代码是一个更大项目的一部分,因此我无法将其全部粘贴到此处,但正如您在图片中看到的那样,绑定可以正常工作。
有人可以告诉我如何更改组合框的文本吗?
我什至尝试过:
遵循
ComboBox.ItemTemplate
结构,如下面的 .xaml.cs 中所示。
设置
SelectedValue
和 SelectedItem
属性。
xaml:
<ComboBox ItemsSource="{Binding ParameterValueList, UpdateSourceTrigger=LostFocus}"
DropDownClosed="ComboBox_DropDownClosed"
LostFocus="ComboBox_DropDownClosed"
SelectionChanged="ComboBox_SelectionChanged"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox
Content="{Binding ValueToString}"
Width="250"
IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
xaml.cs
public partial class MainView : Window
{
private IEventAggregator \_eventAggregator;
public MainView(MainViewViewModel vm, IEventAggregator eventAggregator)
{
InitializeComponent();
_eventAggregator = eventAggregator;
vm.OnRequestClose += (s, e) => this.Close();
DataContext = vm;
}
private void ComboBox_DropDownClosed(object sender, System.EventArgs e)
{
(sender as ComboBox).Text = "test closed";
//(sender as ComboBox).SelectedValue = new CheckBox()
//{
// IsChecked = true,
// Content = "test closed"
//};
//string text = (sender as ComboBox).Text;
}
private void ComboBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ComboBox).Text = "test changed";
//(sender as ComboBox).SelectedItem = new CheckBox()
//{
// IsChecked = true,
// Content = "test Selected"
//};
//(sender as ComboBox).IsDropDownOpen = true;
//string text = (sender as ComboBox).Text;
}
}
据我了解,您希望自定义组合框显示与所选项目的字符串表示形式不同的内容,特别是显示已选中项目的一些指示。
作为一种方法,如果您只是创建一个实际的
CustomComboBox
子类并在内部完成所有这些操作,这样的事情可能会更容易。但无论您是否制作自定义控件,实现目标的一种方法是将 ComboBox
属性设置为 IsEditable
、IsReadOnly
和 !Focusable
。
这就是我的意思。也许这作为一个起点很有用。
C#
class CustomComboBox : ComboBox
{
public CustomComboBox()
{
Height = 30;
Width = 150;
BorderBrush = new SolidColorBrush(Colors.Teal);
BorderThickness = new Thickness(2);
IsEditable = true;
IsReadOnly = true;
Focusable = false;
ItemsSource = new CheckBox[]
{
new CheckBox{ Content = "Dogs" },
new CheckBox{ Content = "Cats" },
new CheckBox{ Content = "Pets" },
};
foreach (var checkBox in ItemsSource.OfType<CheckBox>())
{
checkBox.Checked += Refresh;
checkBox.Unchecked += Refresh;
}
}
void Refresh(object sender, RoutedEventArgs e)
{
var checkedItems = Items
.OfType<CheckBox>()
.Where(_ => _.IsChecked == true)
.Select(_ => $"{_.Content}")
.ToArray();
var countDisplay = checkedItems.Length == 0
? string.Empty
: $"[{checkedItems.Length}] ";
if(checkedItems.Length == 0)
{
if(SelectedItem is CheckBox checkBox)
{
Text = $"{checkBox.Content}";
}
else
{
Text = string.Empty;
}
}
else
{
string selectedNotChecked = string.Empty;
if(SelectedItem is CheckBox checkBox)
{
if (!checkedItems.Any(_ => _ == checkBox.Content?.ToString()))
{
// Append selected item if not checked.
selectedNotChecked = $":[{checkBox.Content}]";
}
}
// If any items are checked, show the verbose display.
if(SelectedIndex != -1 && SelectedIndex<checkedItems.Length)
{
checkedItems[SelectedIndex] = $"[{checkedItems[SelectedIndex]}]";
}
Text = $"{countDisplay}{string.Join(";", checkedItems)}{selectedNotChecked}";
}
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
Refresh(this, new RoutedEventArgs());
}
}
XAML
这里不再需要做任何特别的事情。
<Window x:Class="custom_combo_box.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:custom_combo_box"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="300">
<Window.DataContext>
<local:MainWindowDataContext/>
</Window.DataContext>
<Grid>
<local:CustomComboBox />
</Grid>
</Window>