我试图使一个组合框,有复选框作为项目,并根据什么是检查显示不同的东西时,组合框是“关闭”。我试图实现的外观可以在图像中看到。x1c 0d1x的数据理想情况下,我不希望用户能够选择顶部的文本(在图像中)。有没有简单的解决办法?我见过一些解决方案,其中可以显示更多的信息时,所有的项目显示使用DataTriggers隐藏不同的嵌套控件,但这不是真正的我在寻找什么。有什么想法吗?/Erik
cyvaqqii1#
下面是一种使用ComboBox实现大部分功能的方法,除了文本仍然可以被选择(使用自定义文本仅在IsEditable为true时有效)。由于IsReadOnly="true"的原因,它是不可编辑的。
ComboBox
IsEditable
IsReadOnly="true"
查看
<ComboBox IsEditable="True" IsReadOnly="True" ItemsSource="{Binding Items}" Text="{Binding Text}"> <ComboBox.ItemTemplate> <DataTemplate DataType="{x:Type local:Item}"> <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" /> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
字符串
视图模型
// ObservableObject is a custom base class that implements INotifyPropertyChanged internal class MainWindowVM : ObservableObject { private ObservableCollection<Item> mItems; private HashSet<Item> mCheckedItems; public IEnumerable<Item> Items { get { return mItems; } } public string Text { get { return _text; } set { Set(ref _text, value); } } private string _text; public MainWindowVM() { mItems = new ObservableCollection<Item>(); mCheckedItems = new HashSet<Item>(); mItems.CollectionChanged += Items_CollectionChanged; // Adding test data for (int i = 0; i < 10; ++i) { mItems.Add(new Item(string.Format("Item {0}", i.ToString("00")))); } } private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.OldItems != null) { foreach (Item item in e.OldItems) { item.PropertyChanged -= Item_PropertyChanged; mCheckedItems.Remove(item); } } if (e.NewItems != null) { foreach (Item item in e.NewItems) { item.PropertyChanged += Item_PropertyChanged; if (item.IsChecked) mCheckedItems.Add(item); } } UpdateText(); } private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "IsChecked") { Item item = (Item)sender; if (item.IsChecked) { mCheckedItems.Add(item); } else { mCheckedItems.Remove(item); } UpdateText(); } } private void UpdateText() { switch (mCheckedItems.Count) { case 0: Text = "<none>"; break; case 1: Text = mCheckedItems.First().Name; break; default: Text = "<multiple>"; break; } } } // Test item class // Test item class internal class Item : ObservableObject { public string Name { get; private set; } public bool IsChecked { get { return _isChecked; } set { Set(ref _isChecked, value); } } private bool _isChecked; public Item(string name) { Name = name; } public override string ToString() { return Name; } }
型如果可选文本是个问题,您可能需要创建一个自定义ComboBox控件模板(默认示例here)。或者,您可以使用其他东西来代替ComboBox,并使其看起来像ComboBox。示例屏幕截图:
的数据
r1zhe5dt2#
使用@Erik83和@Xavier解决方案的组合,我仍然遇到了一个问题,即在CheckBox文本的正确位置选择ComboBoxItem会关闭ComboBox-DropDown并显示ComboBoxItem的ToString()值,因为CheckBox没有拉伸到DropDown-Width。我通过加上HorizontalContentAlignment=“拉伸”并添加ItemContainerStyle:
<ComboBox x:Name="combobox" Background="White" Padding="2" Text="{Binding ElementName=DockPanelTemplateComboCheck, Path=ComboTextFilter}" IsEditable="True" IsReadOnly="True" HorizontalAlignment="Stretch" ItemsSource="{Binding ...}" IsDropDownOpen="{Binding Path=DropOpen, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, UpdateSourceTrigger=PropertyChanged}"> <ComboBox.ItemTemplate> <DataTemplate> <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Eintrag}" HorizontalContentAlignment="Stretch" Checked="CheckBox_Checked_Unchecked" Unchecked="CheckBox_Checked_Unchecked"/> </DataTemplate> </ComboBox.ItemTemplate> <ComboBox.ItemContainerStyle> <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> </Style> </ComboBox.ItemContainerStyle> </ComboBox>
字符串CodeBehind:
private string combotextfilter = "<No Selection>"; public string ComboTextFilter { get { return combotextfilter; } set { if (value != null && value.IndexOf("ComboModel") != -1) return; combotextfilter = value; NotifyPropertyChanged(nameof(ComboTextFilter)); } } private void CheckBox_Checked_Unchecked(object sender, RoutedEventArgs e) { switch (((ObservableCollection<ComboModel>)combobox.ItemsSource).Count(x => x.IsChecked)) { case 0: ComboTextFilter = "<No Selection>"; break; case 1: ComboTextFilter = ((ObservableCollection<ComboModel>)combobox.ItemsSource).Where(x => x.IsChecked).First().Eintrag; break; default: ComboTextFilter = ((ObservableCollection<ComboModel>)combobox.ItemsSource).Where(x => x.IsChecked).Select(x => x.Eintrag).Aggregate((i, j) => i + " | " + j); //ComboTextFilter = "<Multiple Selected>"; break; } NotifyPropertyChanged(nameof(C_Foreground)); } public bool DropOpen { get { return dropopen; } set { dropopen = value; NotifyPropertyChanged(nameof(ComboTextFilter)); } } private bool dropopen = false;
型
monwx1rj3#
@Xaviers的答案99%有效。然而,用户能够意外地选择复选框,然后复选框的ToString()显示为所选文本。这实际上可能发生很多。我还没有弄清楚为什么会发生这种情况,但我已经找到了一种方法来防止这种情况。创建一个绑定到组合框的DropDownOpen属性的bool属性,当DropDownOpen更改为false时,这意味着DropDown刚刚关闭,您可能会面临上述问题。因此,这里您只需为视图模型引发propertychanged事件,并传递绑定到组合框的Text属性的属性。
neskvpey4#
添加到所有其他答案中,如果你想摆脱勾选复选框时意外选择值的情况,你可以像下面这样覆盖ComboBoxItem的模板。这将删除原始的ComboBoxItem容器,只留下CheckBox容器,从而消除了该风险。
<ComboBox IsEditable="True" IsReadOnly="True" ItemsSource="{Binding ItemsSource}" Text="{Binding SelectedValues, Mode=OneWay}"> <ComboBox.ItemContainerStyle> <Style TargetType="ComboBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <CheckBox Content="{Binding Item.Value}" IsChecked="{Binding Item.IsChecked}"> </CheckBox> </ControlTemplate> </Setter.Value> </Setter> </Style> </ComboBox.ItemContainerStyle> </ComboBox>
4条答案
按热度按时间cyvaqqii1#
下面是一种使用
ComboBox
实现大部分功能的方法,除了文本仍然可以被选择(使用自定义文本仅在IsEditable
为true时有效)。由于IsReadOnly="true"
的原因,它是不可编辑的。查看
字符串
视图模型
型
如果可选文本是个问题,您可能需要创建一个自定义ComboBox控件模板(默认示例here)。或者,您可以使用其他东西来代替
ComboBox
,并使其看起来像ComboBox
。示例屏幕截图:
的数据
r1zhe5dt2#
使用@Erik83和@Xavier解决方案的组合,我仍然遇到了一个问题,即在CheckBox文本的正确位置选择ComboBoxItem会关闭ComboBox-DropDown并显示ComboBoxItem的ToString()值,因为CheckBox没有拉伸到DropDown-Width。我通过加上
HorizontalContentAlignment=“拉伸”
并添加ItemContainerStyle:
字符串
CodeBehind:
型
monwx1rj3#
@Xaviers的答案99%有效。然而,用户能够意外地选择复选框,然后复选框的ToString()显示为所选文本。这实际上可能发生很多。我还没有弄清楚为什么会发生这种情况,但我已经找到了一种方法来防止这种情况。
创建一个绑定到组合框的DropDownOpen属性的bool属性,当DropDownOpen更改为false时,这意味着DropDown刚刚关闭,您可能会面临上述问题。因此,这里您只需为视图模型引发propertychanged事件,并传递绑定到组合框的Text属性的属性。
neskvpey4#
添加到所有其他答案中,如果你想摆脱勾选复选框时意外选择值的情况,你可以像下面这样覆盖ComboBoxItem的模板。这将删除原始的ComboBoxItem容器,只留下CheckBox容器,从而消除了该风险。
字符串