【问题标题】:Binding object to combobox populates list, but selection changes are not updated in the object in CSharp将对象绑定到组合框填充列表,但选择更改不会在 CSharp 中的对象中更新
【发布时间】:2023-03-24 23:10:02
【问题描述】:

我有一个类ParamObj(它实现了INotifyPropertyChanged),它包含一个DefaultValues 类型的ObservableCollection<Param> 属性。我的Param 类(也实现了INotifyPropertyChanged)包含两个属性:NameIsSelected

单击按钮时,我正在使用TextBlockComboBox 控件填充StackPanel。集合DefaultValues 中的每个Param 都是ComboBox 中的一个选项,其中Name 属性表示该选项的文本,IsSelected 是一个布尔值,表示该选项是否是当前在ComboBox.

Param 类如下:

public class Param : INotifyPropertyChanged
{
    public enum ParamType
    {
        Unknown=-1,
        Text=0,
        Option=1,
        Multi=2
    }

    private string pName = string.Empty;
    private bool pSelected = false;
    private ParamType pType = ParamType.Unknown;

    public string Name { get { return pName; } set { pName = value; OnPropertyChanged("Name"); } }
    public bool IsSelected { get { return pSelected; } set { pSelected = value; OnPropertyChanged("IsSelected"); } }
    public ParamType Type { get { return pType; } }

    public Param(string name, bool selected)
    {
        this.pName = name;
        this.pSelected = selected;
        this.pType = ParamType.Option;
    }

    //INotifyPropertyChanged base
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(name));
    }
}

ParamObj 下面的类:

public class ParamObj : INotifyPropertyChanged
{
    //ui type mapping
    public enum UITypeEnum
    {
        Textbox = 0,
        ComboBox = 1,
        CheckableComboBox = 2
    }

    private string name = string.Empty;
    private UITypeEnum uiType = UITypeEnum.Textbox;
    private ObservableCollection<Param> defaultVals = new ObservableCollection<Param>();
    private string propDescription = string.Empty;

    public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } }
    public UITypeEnum UIType { get { return uiType; } set { uiType = value; OnPropertyChanged("UIType"); } }
    public ObservableCollection<Param> DefaultValues { get { return defaultVals; } }
    public string Desc { get { return propDescription; } set { propDescription = value; } }

    //Initialization
    public ParamObj()
    {

    }

    public void ClearDefaultValues()
    {
        this.defaultVals.Clear();
        OnPropertyChanged("DefaultValues");
    }

    public void AddDefaultValue(Param objAdded)
    {
        this.defaultVals.Add(objAdded);
    }

    public void AddDefaultValueRange(Param[] objsToAdd)
    {
        foreach (Param o in objsToAdd)
        {
            this.defaultVals.Add(o);
        }
    }

    //INotifyPropertyChanged base
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(name));
    }
}

在按钮单击事件中调用下面的代码。 po 代表一个 ParamObj 实例。

case ParamObj.UITypeEnum.ComboBox:
    cb = new ComboBox();
    cb.Height = 26;
    cb.Width = 210;
    cb.Margin = new Thickness(2);
    cb.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
    cb.DataContext = po.DefaultValues;
    //binding
    cb.ItemsSource = po.DefaultValues;
    cb.DisplayMemberPath = "Name";                        
    cb.SelectedValuePath = "IsSelected";
    cb.SelectedValue = true;

    cb.SelectionChanged += ParamComboBox_SelectionChanged;
    break;

这就是问题所在。 ComboBox 项目已成功填充,并选择了 IsSelected 值为 true 的选项(Param 对象)。我想会发生的是,当我更改ComboBox 中的选定选项时,Param 对象的IsSelected 属性值(布尔值)将从false 切换到true。这没有发生。所以我将cb.SelectionChanged += ParamComboBox_SelectionChanged 事件添加到ComboBox

    private void ParamComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (!(sender is ComboBox)) return;

        ComboBox cb = sender as ComboBox;
        Param cp = (Param)cb.SelectedItem;
        if (cp.IsSelected == false)
        {
            foreach (Param p in cb.ItemsSource)
            {
                p.IsSelected = false;
            }
            cp.IsSelected = true;
        }
    }

通过调试,我确实看到IsSelected 属性已正确更新,但我的po 对象中的值并未使用新值进行更新。

非常感谢任何建议。我已经尽了最大的努力来解决这个问题,但我被卡住了。

布赖恩

【问题讨论】:

    标签: c# binding combobox


    【解决方案1】:

    这是看起来非常简单的问题之一,但似乎没有简单或直接的方法将 ComboBoxItem IsSelected 绑定到给定属性。我想到的一种可能的解决方案是:

    首先,将 ComboBoxItem 类型的样式添加到您的 ComboBox 并为该样式添加触发器。当您选择了一个 ComboBoxItem 时,此触发器将触发,并将在第 2 步中调用帮助程序类。

         <ComboBox Name="TestCombo" ItemsSource="{Binding Path=DataSource.DefaultValues}" DisplayMemberPath="Name" SelectedValuePath="IsSelected" SelectionChanged="Test_SelectionChanged">
                    <ComboBox.Resources>                    
                        <Style TargetType="{x:Type ComboBoxItem}">
                            <Style.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="StackOverflow:IsSelectedBehavior.IsSelected" Value="True"></Setter>
                                </Trigger>
                                <Trigger Property="IsSelected" Value="False">
                                    <Setter Property="StackOverflow:IsSelectedBehavior.IsSelected" Value="False"></Setter>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </ComboBox.Resources>
                </ComboBox>
    

    如果你想以编程方式做同样的事情,那么你去:

            Style style = new Style();
            Trigger t = new Trigger();
            style.TargetType = typeof(ComboBoxItem);
            t.Property = ListBoxItem.IsSelectedProperty;
            t.Value = true;
            Setter setter = new Setter(IsSelectedBehavior.IsSelectedProperty, true);
            t.Setters.Add(setter);
            style.Triggers.Add(t);
            cb.Resources.Add(typeof(ComboBoxItem), style);
    

    然后,创建一个 IsSelectedBehaviorClass 来处理您的 IsSelected 行为。这个静态类将接收当前选择的 ComboBoxItem 并相应地设置 Param.IsSelected 属性。像这样的:

        public static class IsSelectedBehavior
        {
            public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.RegisterAttached(
                "IsSelected", typeof (bool), typeof (IsSelectedBehavior), new UIPropertyMetadata(false, OnIsSelected));
    
            public static bool GetIsSelected(DependencyObject d)
            {
                return (bool) d.GetValue(IsSelectedProperty);
            }
    
            public static void SetIsSelected(DependencyObject d, bool value)
            {
                d.SetValue(IsSelectedProperty, value);
            }
    
            public static void OnIsSelected(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                //Get current ComboBoxItem
                ComboBoxItem test = d as ComboBoxItem;
                //Get the current Param from the ComboBoxItem.Content
                Param p = test.Content as Param;
                //Set the Param.IsSelected property
                p.IsSelected = (bool) e.NewValue;
            }
        }
    

    最后你可以在 SelectionChanged EventHandler 上测试你的解决方案

        private void ParamComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                Param selected = cb.SelectedItem as Param;
                if (selected != null)
                {
                    Debug.WriteLine("Selection Changed: Selected " + selected.Name);
                }
                StringBuilder str = new StringBuilder();
                foreach (var obj in cb.Items)
                {
                    Param p = obj as Param;
                    str.Append("Name:" + p.Name + " IsSelected:" + p.IsSelected + Environment.NewLine);
                    Debug.WriteLine(str);
                }
                MessageBox.Show(str.ToString());
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 2011-04-15
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多