ComboBox 中显示的当前值
Current value displayed in ComboBox
当 ComboBox 中的项目是数据库中的自定义对象时,我似乎无法在 ComboBox 中显示当前选定的值。我把下面的测试ViewModel和View放在一起。 SimpleWidgets 和 ObjectWidgets 的行为符合预期。 CodeWidgets(作为自定义 'Code' 对象从数据库中检索的列表)从不显示 SelectedCodeWidget。
public class TestViewModel:BaseTabViewModel
{
private List<int> simpleWidgets;
public List<int> SimpleWidgets
{
get { return simpleWidgets; }
set
{
simpleWidgets = value;
NotifyOfPropertyChange(() => SimpleWidgets);
}
}
private int selectedSimpleWidget;
public int SelectedSimpleWidget
{
get { return selectedSimpleWidget; }
set
{
selectedSimpleWidget = value;
NotifyOfPropertyChange(() => SelectedSimpleWidget);
}
}
private List<Widget> objectWidgets;
public List<Widget> ObjectWidgets
{
get { return objectWidgets; }
set
{
objectWidgets = value;
NotifyOfPropertyChange(() => ObjectWidgets);
}
}
private Widget _selectedObjectWidget;
public Widget SelectedObjectWidget
{
get { return _selectedObjectWidget; }
set
{
_selectedObjectWidget = value;
NotifyOfPropertyChange(() => SelectedObjectWidget);
}
}
private List<ICode> codeWidgets;
public List<ICode> CodeWidgets
{
get { return codeWidgets; }
set
{
codeWidgets = value;
NotifyOfPropertyChange(() => CodeWidgets);
}
}
private Code _selectedCodeWidget;
public Code SelectedCodeWidget
{
get { return _selectedCodeWidget; }
set
{
_selectedCodeWidget = value;
NotifyOfPropertyChange(() => SelectedCodeWidget);
}
}
public TestViewModel()
{
DisplayName = "Test Data";
IsEnabled = true;//control this with permissions
//Simple int comboBox
SimpleWidgets = new List<int> {1, 3, 5, 7, 9};
SelectedSimpleWidget = 7;
//Object filled ComboBox
ObjectWidgets= new List<Widget>();
Widget w = new Widget {Key = 2, Description = "test2"};
ObjectWidgets.Add(w);
w = new Widget { Key = 4, Description = "test4" };
ObjectWidgets.Add(w);
w = new Widget {Key = 6, Description = "test6"};
ObjectWidgets.Add(w);
SelectedObjectWidget = w;
//Code filled ComboBox
CodeWidgets = (new Code().Get("UPFLTY").Result).ToList();
SelectedCodeWidget = new Code(2707);
}
}
public class Widget
{
public int Key { get; set; }
public string Description { get; set; }
}
TestView.xaml是:
<UserControl x:Class="CAB.DataManager.App.Views.TestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UniformGrid>
<ComboBox Name="SimpleWidgets"></ComboBox>
<ComboBox Name="ObjectWidgets"
DisplayMemberPath="Description" >
</ComboBox>
<ComboBox x:Name="CodeWidgets">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</UniformGrid>
</UserControl>
SimpleWidgets 和 ObjectWidgets 显示所选值并在下拉列表中包含所有值。 CodeWidgets 为空白,但下拉列表中包含所有值。我错过了什么?
在 SelectedItem
中的 实例 必须存在于 ItemsSource
.
中
来自您的代码
//Code filled ComboBox
CodeWidgets = (new Code().Get("UPFLTY").Result).ToList();
SelectedCodeWidget = new Code(2707); // THIS is where you bugged!
您可以看到 SelectedCodeWidget
被设置为 Code
的一个新实例,它不在 CodeWidgets
.
中
答案很简单:
//Code filled ComboBox
CodeWidgets = (new Code().Get("UPFLTY").Result).ToList();
var selectedCode = FindCodeByDERP(CodeWidgets, 2707); // MAKE THIS METHOD
SelectedCodeWidget = selectedCode;
其中 FindCodeByDERP
是您编写的一种方法,用于搜索 CodeWidgets
和 returns 中 2707 中最难的实例.不管它是什么意思。我的意思是,您有代码 UPFLTY,但您创建了另一个传入 2707... 的实例,这毫无意义。是的。
WPF 的 ComboBox 通过引用将 SelectedItem 与 ItemsSource 中的那些进行比较,在您的情况下,new Code(2707)
的实例在内存中与 (new Code().Get("UPFLTY").Result).ToList()
[= 中的实例不完全相同19=]
避免这种情况的最常见方法是在具有通用对象类型的对象上使用 SelectedValue
和 SelectedValuePath
。
例如,
<ComboBox x:Name="CodeWidgets"
SelectedValue="{Binding SelectedCodeId}"
SelectedValuePath="Id">
另一个解决方案是确保将 SelectedItem 设置为 ItemsSource 中的项目之一,而不是该项目的新实例。
SelectedCodeWidget = CodeWidgets.FirstOrDefault(() => p.Id == 2707);
第三种解决方案(通常不推荐)是覆盖对象的 .Equals
,以便它通过参考以外的其他内容比较项目
public override bool Equals(object obj)
{
if (obj == null || !(obj is Code))
return false;
return ((Code)obj).Id == this.Id);
}
请注意,如果您也走这条路,您可能还应该覆盖 .GetHashCode()
。
当 ComboBox 中的项目是数据库中的自定义对象时,我似乎无法在 ComboBox 中显示当前选定的值。我把下面的测试ViewModel和View放在一起。 SimpleWidgets 和 ObjectWidgets 的行为符合预期。 CodeWidgets(作为自定义 'Code' 对象从数据库中检索的列表)从不显示 SelectedCodeWidget。
public class TestViewModel:BaseTabViewModel
{
private List<int> simpleWidgets;
public List<int> SimpleWidgets
{
get { return simpleWidgets; }
set
{
simpleWidgets = value;
NotifyOfPropertyChange(() => SimpleWidgets);
}
}
private int selectedSimpleWidget;
public int SelectedSimpleWidget
{
get { return selectedSimpleWidget; }
set
{
selectedSimpleWidget = value;
NotifyOfPropertyChange(() => SelectedSimpleWidget);
}
}
private List<Widget> objectWidgets;
public List<Widget> ObjectWidgets
{
get { return objectWidgets; }
set
{
objectWidgets = value;
NotifyOfPropertyChange(() => ObjectWidgets);
}
}
private Widget _selectedObjectWidget;
public Widget SelectedObjectWidget
{
get { return _selectedObjectWidget; }
set
{
_selectedObjectWidget = value;
NotifyOfPropertyChange(() => SelectedObjectWidget);
}
}
private List<ICode> codeWidgets;
public List<ICode> CodeWidgets
{
get { return codeWidgets; }
set
{
codeWidgets = value;
NotifyOfPropertyChange(() => CodeWidgets);
}
}
private Code _selectedCodeWidget;
public Code SelectedCodeWidget
{
get { return _selectedCodeWidget; }
set
{
_selectedCodeWidget = value;
NotifyOfPropertyChange(() => SelectedCodeWidget);
}
}
public TestViewModel()
{
DisplayName = "Test Data";
IsEnabled = true;//control this with permissions
//Simple int comboBox
SimpleWidgets = new List<int> {1, 3, 5, 7, 9};
SelectedSimpleWidget = 7;
//Object filled ComboBox
ObjectWidgets= new List<Widget>();
Widget w = new Widget {Key = 2, Description = "test2"};
ObjectWidgets.Add(w);
w = new Widget { Key = 4, Description = "test4" };
ObjectWidgets.Add(w);
w = new Widget {Key = 6, Description = "test6"};
ObjectWidgets.Add(w);
SelectedObjectWidget = w;
//Code filled ComboBox
CodeWidgets = (new Code().Get("UPFLTY").Result).ToList();
SelectedCodeWidget = new Code(2707);
}
}
public class Widget
{
public int Key { get; set; }
public string Description { get; set; }
}
TestView.xaml是:
<UserControl x:Class="CAB.DataManager.App.Views.TestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UniformGrid>
<ComboBox Name="SimpleWidgets"></ComboBox>
<ComboBox Name="ObjectWidgets"
DisplayMemberPath="Description" >
</ComboBox>
<ComboBox x:Name="CodeWidgets">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</UniformGrid>
</UserControl>
SimpleWidgets 和 ObjectWidgets 显示所选值并在下拉列表中包含所有值。 CodeWidgets 为空白,但下拉列表中包含所有值。我错过了什么?
在 SelectedItem
中的 实例 必须存在于 ItemsSource
.
来自您的代码
//Code filled ComboBox
CodeWidgets = (new Code().Get("UPFLTY").Result).ToList();
SelectedCodeWidget = new Code(2707); // THIS is where you bugged!
您可以看到 SelectedCodeWidget
被设置为 Code
的一个新实例,它不在 CodeWidgets
.
答案很简单:
//Code filled ComboBox
CodeWidgets = (new Code().Get("UPFLTY").Result).ToList();
var selectedCode = FindCodeByDERP(CodeWidgets, 2707); // MAKE THIS METHOD
SelectedCodeWidget = selectedCode;
其中 FindCodeByDERP
是您编写的一种方法,用于搜索 CodeWidgets
和 returns 中 2707 中最难的实例.不管它是什么意思。我的意思是,您有代码 UPFLTY,但您创建了另一个传入 2707... 的实例,这毫无意义。是的。
WPF 的 ComboBox 通过引用将 SelectedItem 与 ItemsSource 中的那些进行比较,在您的情况下,new Code(2707)
的实例在内存中与 (new Code().Get("UPFLTY").Result).ToList()
[= 中的实例不完全相同19=]
避免这种情况的最常见方法是在具有通用对象类型的对象上使用 SelectedValue
和 SelectedValuePath
。
例如,
<ComboBox x:Name="CodeWidgets"
SelectedValue="{Binding SelectedCodeId}"
SelectedValuePath="Id">
另一个解决方案是确保将 SelectedItem 设置为 ItemsSource 中的项目之一,而不是该项目的新实例。
SelectedCodeWidget = CodeWidgets.FirstOrDefault(() => p.Id == 2707);
第三种解决方案(通常不推荐)是覆盖对象的 .Equals
,以便它通过参考以外的其他内容比较项目
public override bool Equals(object obj)
{
if (obj == null || !(obj is Code))
return false;
return ((Code)obj).Id == this.Id);
}
请注意,如果您也走这条路,您可能还应该覆盖 .GetHashCode()
。