快速解决方案
为您的 ComboItems 创建一个源类,其中包含(至少)要显示的属性和属性的内部值。如果您创建一个泛型类,您可以将它用于您的所有组合框。
class ComboDisplay<TSource>
{
public string Display {get; set;}
public TSource Value {get; set;}
}
cmbRoom.DisplayMember = nameof(ComboDisplay.Display);
cmbRoom.ValueMember = nameof(ComboDisplay.Value);
为组合框创建数据源时,请确保添加默认值。在下面的示例中,我假设您要在组合中选择 Room 类型的项目:
IEnumerable<Room> availableRooms = myDbContext.Rooms
.Where(room => room.IsAvailable)
.Select(room => new ComboDisplay<Room>
{
Display = room.Name,
Value = new Room
{
Id = room.Id,
...
},
})
// add a dummy value if nothing is selected
.Concat(new Room[]
{
Display = "Please select a room",
Value = null, // meaning: nothing selected
});
选中后,使用comboBox1.SelectedValue获取选中的Room,如果没有选中则为null。
创建一个特殊的组合框类
如果你必须经常使用它,可以考虑创建一个通用的 ComboBox 子类,它可以显示某个 TSource 的项目,如果没有选择则返回 null:
class MyComboBox<TSource> : ComboBox
{
public MyComboBox() : base()
{
base.DataSource = this.EmptyList;
base.DisplayMember = nameof(ComboDisplay.Display);
base.ValueMember = nameof(ComboDisplay.Value);
}
private static readonly EmptyItem = new ComboDisplay
{
Display = "Please select a value",
Value = null,
}
创建一个返回可用组合项的属性。确保 EmptyItem 始终在集合中:
public IReadonlyCollection<TSource> ComboItems
{
get {return (IReadOnlyCollection<TSource>)base.DataSource;}
set
{
// TODO: check if the empty element is in your list; if not add it
base.DataSource = value;
}
}
最后:获取 Selected 值的函数,如果没有选择,则返回 null:
public TSource SelectedValue
{
get => return (TSource)base.SelectedValue;
set
{
// TODO: check if value is in ComboItems
base.SelectedValue = value;
}
}