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

时间:2016-02-25 03:02:39

标签: c# indexof checkedlistbox listboxitems

我有这段代码:

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.但是,即使在中的人,这个行:

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

......找不到它们。 “assignedStudent.FullName”的值确实等于其中一个项的值;如上所示,“FullName”是CheckedListBox的ValueMember:

通过它,学生名单,BR学生,有2名成员,已经分配的人和另一个人; “assignedStudent”是已经分配的人; checkedListBoxBR有三个项目,已经分配的人员加上两个其他人。

那么,当分配的人员在FullName中表示时,为什么assignStudentIndex为-1?确实,我没有在这一行中明确指定FullName:

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

...但FullName是类中的计算字段:

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 { } 
    }
}

那么为什么在TarnedListBox的项目中,当它最明显存在时,为什么在tarnation中找不到“So and So”?

更新

Olivier的建议似乎很好(“遍历checkedListBoxBR.Items,看看你是否找到了项目的DisplayMember和assignedStudent.FullName之间的匹配”)。但是怎么样?我想也许这样的事情可以做到:

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

...但此处未识别“DisplayMember”(也不是“RemoveAt”)。

更新2

回应Olivier的推动,我将上述内容修正为:

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);
}

2 个答案:

答案 0 :(得分:2)

我可以看到两件事情错了。

首先,在之后填写checkedListBoxBR ,检查是否存在某个项目。

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

更好的解决方案是遍历checkedListBoxBR.Items,看看您是否找到了项目DisplayMemberassignedStudent.FullName之间的匹配项。

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

答案 1 :(得分:1)

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

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

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

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

此外,您可能需要override the Equals method

修改: 正如@ olivier-de-meulder正确指出的那样,您需要将这些行移到查找上方以使任何选项有效:

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