Как добавить DisplayMember и ValueMember к одному элементу ComboBox с назначенным источником данных?
Я успешно добавляю пары Display/Value в комбинированный список следующим образом:
List<Student> BRStudents =
studentsList.Where(h => h.EnrolledInAYttFM)
.Where(i =>
i.RecommendedNextTalkTypeID.Equals(BIBLE_READING_TALK_TYPE))
.OrderBy(j => j.WeekOfLastAssignment)
.ToList();
comboBoxBR.DataSource = BRStudents;
comboBoxBR.DisplayMember = "FullName";
comboBoxBR.ValueMember = "StudentID";
... но я тогда (в некоторых случаях) хочу добавить еще один элемент в comboBoxBR, который отсутствует в списке BRStudents. Если я попытаюсь сделать это:
AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
.FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == 1);
string fullName = AYttFMConstsAndUtils.GetStudentFullNameForID(ah.StudentID_FK);
comboBoxBR.Items.Add(fullName);
... Я получаю, "Коллекция предметов не может быть изменена, когда установлено свойство DataSource."
На самом деле, я хочу сделать что-то вроде этого:
comboBoxBR.Items.Add(fullName, ah.StudentID_FK);
Есть ли способ объединить два результата (список Student и одну AssignmentHistory) в словарь или некоторую подобную коллекцию, а затем назначить его в качестве источника данных для comboBoxBR?
Для полного раскрытия, вот определения Студента и AssignmentHistory:
public class Student
{
public int StudentID { get; set; }
public int FamilyID { get; set; }
public bool EnrolledInAYttFM { get; set; }
public DateTime DateEnrolledOrHiatusAYttFM { get; set; }
public bool GivesBibleReading { get; set; }
public bool PresentsICRVBS { get; set; }
public bool IsHouseholder { get; set; }
public bool IsMale { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddr { get; set; }
public DateTime WeekOfLastAssignment { get; set; }
public int RecommendedNextTalkTypeID { get; set; }
public int NextCounselPoint { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
public class AssignmentHistory
{
public DateTime WeekOfAssignment { get; set; }
public int TalkType { get; set; }
public int StudentID_FK { get; set; }
public int AssistantID_FK { get; set; }
public int CounselPoint { get; set; }
public bool HasBeenEmailed { get; set; }
public bool SlipHasBeenPrinted { get; set; }
}
1 ответ
Вместо добавления элементов в коллекцию Items комбо (невозможно, если вы установили DataSource), первое, что приходит на ум, - это добавление элементов в List<Students>
сам по себе используется в качестве источника данных, но это не достигает вашей цели, поскольку отсутствует механизм информирования ComboBox о том, что в источнике данных появился новый элемент. Вы не сможете увидеть добавленный элемент, если не перепривязать список к списку. Для этого сначала нужно отменить привязку предыдущего источника данных, а затем снова связать список.
// Assuming a lot about your student class, hope it's clear the intention
BRStudents.Add(new Student() { newName = "ANewStudent", ID = 1} );
comboBoxBR.DataSource = null;
comboBoxBR.DataSource = BRStudents;
comboBoxBR.DisplayMember = "FullName";
comboBoxBR.ValueMember = "StudentID";
Тем не менее, есть лучшее решение, и это класс BindingList(T)
Этот класс способен обновлять объект, к которому вы привязываете его экземпляр.
Поэтому, когда вы связываете комбо в первый раз, вы должны написать
BindingList<Student> bl = new BindingList<Student>(BRStudents);
comboBoxBR.DataSource = bl;
comboBoxBR.DisplayMember = "FullName";
comboBoxBR.ValueMember = "StudentID";
и когда вы хотите добавить новый элемент в список, вы пишете
(при необходимости переместите bl в глобальную область)
bl.Add(new Student() { newName = "ANewStudent", ID = 1} );
В документации говорится, что вы должны вызывать ResetBindings для принудительного обновления элемента управления, но это не всегда требуется...