为什么无法通过 IndexOf() 找到 CheckedListBox 中存在的项

本文关键字:CheckedListBox 找到 存在 IndexOf 为什么 | 更新日期: 2023-09-27 18:36:09

我有这个代码:

if (currentWeekSaved)
{
    DateTime currentWeek = Convert.ToDateTime(comboBoxWeekToSchedule.SelectedValue);
    AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
        .FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == BIBLE_READING_TALK_TYPE);
    if (ah != null)
    {
        var assignedStudentFirstname = AYttFMConstsAndUtils.GetStudentFirstNameForID(ah.StudentID_FK);
        var assignedStudentLastname = AYttFMConstsAndUtils.GetStudentLastNameForID(ah.StudentID_FK);
        assignedStudent = new Student() {FirstName = assignedStudentFirstname, LastName = assignedStudentLastname, StudentID = ah.StudentID_FK};
    }
}
List<Student> BRStudents =
    AYttFMConstsAndUtils.StudentsList.Where(h => h.EnrolledInAYttFM)
        .Where(i => i.RecommendedNextTalkTypeID.Equals(BIBLE_READING_TALK_TYPE))
        .OrderBy(j => j.WeekOfLastAssignment)
        .ToList();
if (null != assignedStudent)
{
    // If exists in list, remove it first, and then add it back at the top
    //int assignedStudentIndex = BRStudents.IndexOf(assignedStudent);
    int assignedStudentIndex = checkedListBoxBR.Items.IndexOf(assignedStudent.FullName);
    if (assignedStudentIndex > -1)
    {
        BRStudents.RemoveAt(assignedStudentIndex);
    }
    BRStudents.Insert(0, assignedStudent);
}
checkedListBoxBR.DataSource = BRStudents;
checkedListBoxBR.DisplayMember = "FullName";
checkedListBoxBR.ValueMember = "StudentID";

如果已经为正在处理的一周分配了某人,我想首先从checkedListBoxBR中删除他们,然后将它们添加回索引0处。但是,即使此人在选中ListBoxBR,此行:

int assignedStudentIndex = 
    checkedListBoxBR.Items.IndexOf(assignedStudent.FullName);

。找不到它们。"assignedStudent.FullName"的值等于其中一个项目的值;如上所示,"FullName"是CheckedListBox的值成员:

在逐步浏览它时,学生列表 BRStudents 有 2 名成员,已经分配的人和另一个人;"已分配学生"是已分配的人;checkedListBoxBR 有三个项目,已分配的人员加上另外两个项目。

那么,当被分配的人以全名表示时,为什么分配的学生索引为 -1?确实,我没有在此行中显式分配全名:

assignedStudent = new Student() {FirstName = assignedStudentFirstname, LastName = assignedStudentLastname, StudentID = ah.StudentID_FK};

。但全名是类中的计算字段:

public class Student
{
    public int StudentID { get; set; }
    . . .
    public string FirstName { get; set; }
    public string LastName { get; set; }
    . . .
    public string FullName
    {
        get
        {
            return $"{FirstName} {LastName}";
        }
        set { } 
    }
}

那么,为什么在CheckedListBox的项目中找不到"某某"呢?

更新

Olivier 的建议似乎不错("遍历 checkedListBoxBR.Items 并查看是否在项目的 DisplayMember 和 asignedStudent.FullName 之间找到匹配项")。但是怎么做呢?我想也许这样的事情会做到:

for (int i = 0; i < checkedListBoxBR.Items.Count; i++)
{
    if checkedListBoxBR.Items[0].DisplayMember.Equals(assignedStudent.FullName)
    {
        checkedListBoxBR.RemoveAt(i);
    }
}

。但此处无法识别"DisplayMember"("RemoveAt"也不识别)。

更新 2

为了回应奥利维尔的轻推,我将上述内容固定为:

for (int i = 0; i < checkedListBoxBR.Items.Count; i++)
{
    if checkedListBoxBR.Items[i].DisplayMember.Equals(assignedStudent.FullName)
    {
        checkedListBoxBR.Items.RemoveAt(i);
    }
}

。但它仍然认为DisplayMember是不受欢迎的财产。

更新 3

我已经简化了代码,它运行良好。这是简化版本:

// Called whenever the week changes (a new week is navigated to/selected in the combobox)
private void PopulateBibleReadingComboBox()
{
    int BIBLE_READING_TALK_TYPE = 1;
    Student assignedStudent = null;
    List<Student> assignedStudents = null;
    // If the week has been saved, get the student who has been assigned the Bible Reading
    if (currentWeekSaved)
    {
        DateTime currentWeek = Convert.ToDateTime(comboBoxWeekToSchedule.SelectedValue);
        AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
            .FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == BIBLE_READING_TALK_TYPE);
        if (ah != null)
        {
            var assignedStudentFirstname = AYttFMConstsAndUtils.GetStudentFirstNameForID(ah.StudentID_FK);
            var assignedStudentLastname = AYttFMConstsAndUtils.GetStudentLastNameForID(ah.StudentID_FK);
            assignedStudent = new Student() {FirstName = assignedStudentFirstname, LastName = assignedStudentLastname, StudentID = ah.StudentID_FK};
            // Use the ID to get the student and put him/her in a 1-person list (needed for
            // the subsequent LINQ Union)
            assignedStudents =
                AYttFMConstsAndUtils.StudentsList.Where(i => i.StudentID == ah.StudentID_FK).ToList();
        }
    }
    // Get all the candidates for assignment
    List<Student> BRStudents =
    AYttFMConstsAndUtils.StudentsList.Where(h => h.EnrolledInAYttFM)
        .Where(i => i.RecommendedNextTalkTypeID.Equals(BIBLE_READING_TALK_TYPE))
        .OrderBy(j => j.WeekOfLastAssignment)
        .ToList();
    if (null != assignedStudent) 
    {
        List<Student> allBRStudents = assignedStudents.Union(BRStudents).ToList();
        checkedListBoxBR.DataSource = allBRStudents;
        checkedListBoxBR.DisplayMember = "FullName";
        checkedListBoxBR.ValueMember = "StudentID";
    }
    else // No assigned student found, bind to the candidate students only
    {
        checkedListBoxBR.DataSource = BRStudents;
        checkedListBoxBR.DisplayMember = "FullName";
        checkedListBoxBR.ValueMember = "StudentID";
    }
    // In either case, highlight and check the first one now
    checkedListBoxBR.SelectedIndex = 0;
    checkedListBoxBR.SetItemChecked(0, true);
}

为什么无法通过 IndexOf() 找到 CheckedListBox 中存在的项

我可以看到两件事是错误的。

首先,在检查某个项目是否存在填充checkedListBoxBR

其次,您正在比较苹果和橙子。 checkedListBoxBR.Items 是一个对象的集合,你通过 indexOf 将其与字符串 (assignedStudent.FullName) 进行比较。那行不通。

更好的解决方案是遍历checkedListBoxBR.Items,看看是否发现项目的DisplayMemberassignedStudent.FullName匹配。

或者你可以在 indexOf 调用中使用 Student 对象,但你需要确保实现 IEquatable、覆盖 Equals、GetHashCode 等。

checkedListBoxBR的项目属于 Student 类型,因为数据源中的项目属于 Student 类型:

List<Student> BRStudents = [...]
checkedListBoxBR.DataSource = BRStudents;

通过使用带有字符串 (Student.FullName) 的 IndexOf 函数作为参数,您可以将许多Student对象与一个字符串进行比较。没有Student等于你的字符串,所以你会得到 -1 的结果。尝试像这样修改代码:

int assignedStudentIndex = checkedListBoxBR.Items.IndexOf(assignedStudent);

此外,您可能希望重写 Equals 方法。

编辑:正如@olivier-de-meulder正确指出的那样,您需要将这些行移动到查找上方才能使任何选项正常工作:

checkedListBoxBR.DataSource = BRStudents;
checkedListBoxBR.DisplayMember = "FullName";
checkedListBoxBR.ValueMember = "StudentID";