[英]Binding object to combobox populates list, but selection changes are not updated in the object in CSharp
I have a class ParamObj
(which implements INotifyPropertyChanged
) which contains a property DefaultValues
of type ObservableCollection<Param>
. 我有一个类
ParamObj
(实现INotifyPropertyChanged
),其中包含类型为ObservableCollection<Param>
的属性DefaultValues
。 My Param
class (which also implements INotifyPropertyChanged
) contains two properties: Name
and IsSelected
. 我的
Param
类(也实现INotifyPropertyChanged
)包含两个属性: Name
和IsSelected
。
On button click I am populating a StackPanel
with TextBlock
and ComboBox
controls. 在按钮上单击,我正在用
TextBlock
和ComboBox
控件填充StackPanel
。 Each Param
in the collection DefaultValues
is an option in the ComboBox
, where the Name
property represents the text of that option and IsSelected
is a boolean value representing if that option is the one currently selected in the ComboBox
. 集合
DefaultValues
中的每个Param
是ComboBox
一个选项,其中Name
属性表示该选项的文本, IsSelected
是一个布尔值,表示该选项是否是ComboBox
当前选择的选项。
Param
class below: 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
class below: 下面的
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));
}
}
Code below is called in the button click event. 下面的代码在按钮单击事件中调用。
po
represents a ParamObj
instance. 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;
Here's the problem. 这是问题所在。
ComboBox
items are populated successfully and the option ( Param
object) that has an IsSelected
value of true
is selected. ComboBox
项目已成功填充,并且选择了IsSelected
值为true
的选项( Param
对象)。 What I thought would happen is that when I changed the selected option in the ComboBox
the IsSelected
property's value (boolean) of the Param
object would be toggled from false
to true
. 我以为会发生什么事,当我在
ComboBox
更改selected选项时, Param
对象的IsSelected
属性值(布尔值)将从false
切换为true
。 This didn't happen. 这没有发生。 So I added the
cb.SelectionChanged += ParamComboBox_SelectionChanged
event to the ComboBox
. 所以我将
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;
}
}
Through debugging I do see that the IsSelected
properties are correctly updated, but the values in my po
object are not updated with the new values. 通过调试,我确实看到
IsSelected
属性已正确更新,但是po
对象中的值未使用新值更新。
Any suggestions are greatly appreciated. 任何建议,不胜感激。 I've tried my darndest to figure this out but I'm stuck.
我已经尽我最大的努力解决了这个问题,但是我被困住了。
Brian 布赖恩
This is one of the problems that appear to be very simple, but seems like there is no easy or direct way to bind the ComboBoxItem IsSelected to a given property. 这是看起来很简单的问题之一,但是似乎没有简单或直接的方法将ComboBoxItem IsSelected绑定到给定的属性。 One possible solution that comes to my mind could be:
我想到的一种可能的解决方案可能是:
First, Add a Style of type ComboBoxItem to your ComboBox and add a Trigger to that style. 首先,将类型为ComboBoxItem的样式添加到ComboBox中,然后将触发器添加到该样式。 This trigger will fire when you have selected a ComboBoxItem and will call the helper class in step 2.
选择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>
If you want to do this same thing programmatically, then you go: 如果要以编程方式执行此操作,则可以执行以下操作:
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);
Then, Create a IsSelectedBehaviorClass to handle your IsSelected Behavior. 然后,创建一个IsSelectedBehaviorClass来处理IsSelected行为。 This static class will receive the currently selected ComboBoxItem and set the Param.IsSelected property accordingly.
该静态类将接收当前选择的ComboBoxItem并相应地设置Param.IsSelected属性。 Something like this:
像这样:
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;
}
}
Finally you can test your solution on the SelectionChanged EventHandler 最后,您可以在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());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.