我正在尝试使用特定记录中的数据填充多个ComboBox。我可以让其中一个正常运行,但我认为一个概念错误阻止我让第二个正常工作。我搜索了SelectedItem,SelectedValue和SelectedIndex的各种线程,并尝试在提供指导后设计我的代码。显然我做错了什么,但不确定是什么。我所学的一切都是从互联网上自学的,我是一个新手。
我正在使用Entity Framework 6 Database First数据模型。我有一个表(Master),它有一个链接到Shift的外键,另一个表用于Personnel表。 Shift表具有ShiftId(PK)字段,其Identity设置为true,Shift设置为字符串。 Personnel表有PersonnelId(PK),其Identity设置为false(我从其他地方手动填充ID)以及名字和姓氏字段。
我项目的所需流程是:1)获取当前记录,2)填充Shift ComboBox,3)显示与当前记录关联的班次,4)填充Personnel ComboBox,5)显示与之关联的人员当前记录,6)保存对记录的任何更改(通过为任一组合框选择不同的值而建立的更改)。
我的ViewModel正在使用INotifyPropertyChanged,我认为我已经正确实现了这一点,因为Shift ComboBox功能正常。
1)获得所需的记录工作正常。然后将其存储为“CurrentRecord”
2)填充Shift ComboBox工作正常 在我的模型中,我有:
private ICollection<Gen_All_Shift> shiftList;
public ICollection<Gen_All_Shift> GetShiftList()
{
shiftList = context.Gen_All_Shift.OrderBy(p => p.ShiftId)
.ToArray();
return shiftList;
}
在 ViewModel 中,我有:
public ICollection<Gen_All_Shift> ShiftList
{
get { return context.GetShiftList(); }
}
private Gen_All_Shift selectedShift;
public Gen_All_Shift SelectedShift
{
get { return selectedShift; }
set
{
if (value != selectedShift)
{
selectedShift = value;
NotifyPropertyChanged("SelectedShift");
}
}
}
然后 XAML 是:
<ComboBox x:Name="cboShift"
ItemsSource="{Binding ShiftList}"
DisplayMemberPath="Shift"
SelectedIndex="{Binding CurrentRecord.ShiftIdFk,
UpdateSourceTrigger=PropertyChanged}" />
3)只要我绑定到SelectedIndex ,显示当前班次就可以 。如果我使用SelectedItem或SelectedValue,则在加载屏幕时ComboBox为空。 (我也尝试绑定到SelectedShift.ShiftId,但这并没有给我想要的结果。)SelectedIndex将允许我更改选择并允许我将更改正确保存到实际数据库。我不确定我做错了什么阻止了SelectedItem或SelectedValue的工作。不理解这是导致我遇到人员组合框的问题。我相信。
4)填充人员ComboBox的工作原理。
在模型中,我有:
private ICollection<Personnel_All_PersonnelList> personnelList;
public ICollection<Personnel_All_PersonnelList> GetPersonnelList()
{
personnelList = context.Personnel_All_PersonnelList.Where(p=>p.Active == true)
.OrderBy(p => p.LastName)
.ThenBy(p => p.FirstName)
.ToArray();
return personnelList;
}
在 ViewModel 中,我有:
public ICollection<Personnel_All_PersonnelList> PersonnelList
{
get
{
return context.GetPersonnelList();
}
}
private Personnel_All_PersonnelList selectedPerson;
public Personnel_All_PersonnelList SelectedPerson
{
get { return selectedPerson; }
set
{
if (value != selectedPerson)
{
selectedPerson = value;
NotifyPropertyChanged("SelectedPerson");
}
}
}
然后在我的 XAML 中,我有:
<ComboBox x:Name="cboTechnician"
ItemsSource="{Binding PersonnelList}"
DisplayMemberPath="LastName"
SelectedIndex="{Binding CurrentRecord.PersonnelIdFk,
UpdateSourceTrigger=PropertyChanged}" />
5)无论我尝试哪种方式(SelectedIndex,SelectedItem,SelectedValue),显示当前人都不起作用。我猜测SelectedIndex的原因与它对shift的作用方式不同是因为索引号与PersonnelId没有正确对齐,所以系统不知道实际选择了哪一个。
6)如果仅更改Shift,则保存对记录的更改。如果我在Personnel ComboBox中选择一个人并尝试保存,我会收到System Null Exception。我认为这是由于阻止SelectedIndex使用人员组合框的相同问题引起的。
我想如果有人可以指出我正确的方向,为什么我无法使SelectedItem的绑定正常工作,我将能够弄清楚如何修复Personnel ComboBox。
答案 0 :(得分:1)
你尝试过的第一件事实际上是正确的,但有一些事情会让你失望。
例如:
get { return context.GetShiftList(); }
一般来说,这是不一个好主意。任何调用此属性的人都会调用数据库调用每次,这会影响性能并且根本不需要。
更好的想法是调用一个方法来加载 ShiftList
属性,例如:
public void ReloadShiftList()
{
//TODO: Your logic here
ShiftList = ...
}
注意:请确保在INotifyPropertyChanged
属性上实施ShiftList
,以便在更改此属性时更新视图。
对于您的ComboBox
,绑定到SelectedItem
肯定是首选方法。首次加载时所选项目空白的原因是因为SelectedShift
设置为null。要解决此问题,您只需在加载SelectedShift
后设置ShiftList
。
ShiftList = ...
SelectedShift = ShiftList.FirstOrDefault();
通过将SelectedShift
设置为.FirstOrDefault()
的{{1}},您可以保证始终 选择在ShiftList
中(除非ComboBox
中没有项目。)
最后,你的绑定看起来像这样:
ShiftList
答案 1 :(得分:0)
@ Mike Eason - 谢谢,这给了我所需要的东西!
Shift的 ViewModel 现在如下所示:
private ICollection<Gen_All_Shift> shiftList;
public ICollection<Gen_All_Shift> ShiftList
{
get { return shiftList; }
set { shiftList = value; NotifyPropertyChanged("ShiftList"); }
}
private Gen_All_Shift selectedShift;
public Gen_All_Shift SelectedShift
{
get { return selectedShift; }
set { selectedShift = value; NotifyPropertyChanged("SelectedShift"); }
}
public void LoadShiftList()
{
ShiftList = context.GetShiftList();
SelectedShift = ShiftList.Where(p => p.ShiftId == CurrentRecord.ShiftIdFk)
.FirstOrDefault();
}
在ViewModel构造函数中调用LoadShiftList()。
然后 XAML 现在根据需要将绑定设置为SelectedItem:
<ComboBox x:Name="cboShift"
ItemsSource="{Binding ShiftList}"
DisplayMemberPath="Shift"
SelectedItem="{Binding SelectedShift}" />
以前我一直试图设置SelectedShift.ShiftId == CurrentRecord.ShiftIdfk。这一直给我一个空例外。指出要使用.FirstOrDefault()让我回到了正确的道路上。再次感谢。