组合框手动设置文本属性不起作用

问题描述 投票:0回答:1

由于 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;
    }

}
c# wpf xaml combobox
1个回答
0
投票

据我了解,您希望自定义组合框显示与所选项目的字符串表示形式不同的内容,特别是显示已选中项目的一些指示。

作为一种方法,如果您只是创建一个实际的

CustomComboBox
子类并在内部完成所有这些操作,这样的事情可能会更容易。但无论您是否制作自定义控件,实现目标的一种方法是将
ComboBox
属性设置为
IsEditable
IsReadOnly
和 !
Focusable

这就是我的意思。也许这作为一个起点很有用。


C#

screenshot

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>
© www.soinside.com 2019 - 2024. All rights reserved.