C# 将对象绑定到combobox会填充列表,但选择更改不会在CSharp中的对象中更新
我有一个类C# 将对象绑定到combobox会填充列表,但选择更改不会在CSharp中的对象中更新,c#,binding,combobox,C#,Binding,Combobox,我有一个类ParamObj(它实现了INotifyPropertyChanged),其中包含类型为observeCollection的属性DefaultValues。MyParam类(也实现了INotifyPropertyChanged)包含两个属性:Name和IsSelected 单击按钮时,我正在用TextBlock和ComboBox控件填充StackPanel。集合DefaultValues中的每个Param都是ComboBox中的一个选项,其中Name属性表示该选项的文本,IsSelec
ParamObj
(它实现了INotifyPropertyChanged
),其中包含类型为observeCollection
的属性DefaultValues
。MyParam
类(也实现了INotifyPropertyChanged
)包含两个属性:Name
和IsSelected
单击按钮时,我正在用TextBlock
和ComboBox
控件填充StackPanel
。集合DefaultValues
中的每个Param
都是ComboBox
中的一个选项,其中Name
属性表示该选项的文本,IsSelected
是一个布尔值,表示该选项是否是当前在组合框中选择的选项
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;
}
}
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));
}
}
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));
}
}
ParamObj
以下类别:
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));
}
}
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));
}
}
问题出在这里<代码>组合框
项已成功填充,并且选择了IsSelected
值为true
的选项(Param
对象)。我认为会发生的是,当我在组合框中更改所选选项时,参数对象的IsSelected属性值(布尔值)将从false
切换到true
。这没有发生。因此,我将cb.SelectionChanged+=ParamComboBox\u 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
对象中的值未使用新值更新
如有任何建议,我们将不胜感激。我尽了最大的努力想弄明白,但我被卡住了
Brian这似乎是一个非常简单的问题,但似乎没有简单或直接的方法将ComboBoxItem IsSelected绑定到给定属性。我想到的一个可能的解决方案是:
首先,向ComboBox中添加ComboBoxItem类型的样式,并向该样式添加触发器。当您选择ComboBoxItem并在步骤2中调用helper类时,将触发此触发器
<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>
然后,创建一个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());
}
这是看起来非常简单的问题之一,但是似乎没有简单或直接的方法将ComboBoxItem IsSelected绑定到给定的属性。我想到的一个可能的解决方案是:
首先,向ComboBox中添加ComboBoxItem类型的样式,并向该样式添加触发器。当您选择ComboBoxItem并在步骤2中调用helper类时,将触发此触发器
<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>
然后,创建一个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());
}