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

C# 为什么无法通过IndexOf()找到CheckedListBox中存在的项?,c#,indexof,checkedlistbox,listboxitems,C#,Indexof,Checkedlistbox,Listboxitems,我有以下代码: if (currentWeekSaved) { DateTime currentWeek = Convert.ToDateTime(comboBoxWeekToSchedule.SelectedValue); AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList .FirstOrDefault(i => i.WeekOfAssignment == currentWeek

我有以下代码:

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";
…找不到他们。“assignedStudent.FullName”的值不等于其中一项的值;如上所述,“FullName”是CheckedListBox的ValueMember:

一步一步地通过它,学生名单,BRStudents,有2个成员,一个已经被分配的人和另一个人;“指定学生”是指已指定的人员;checkedListBoxBR有三项,即已分配的人员加上另外两项

那么,当被分配的人以全名表示时,为什么被分配的StudentIndex-1是?确实,我没有在这一行中显式指定FullName:

int assignedStudentIndex = 
    checkedListBoxBR.Items.IndexOf(assignedStudent.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 { } 
    }
}
那么,为什么“某某”在CheckedListBox的项目中找不到,而它最明显地在那里呢

更新 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);
    }
}
for(int i=0;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);
    }
}
for(int i=0;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);
}
//每周更改时调用(新的一周导航到/在组合框中选择)
private void PopulateBibleReadingComboBox()
{
int BIBLE_READING_TALK_TYPE=1;
Student assignedStudent=null;
List assignedStudents=null;
//如果本周已被保存,则让被分配阅读圣经的学生阅读
如果(当前周已保存)
{
DateTime currentWeek=Convert.ToDateTime(comboBoxWeekToSchedule.SelectedValue);
AssignmentHistory ah=AYTTFMConstandUtils.AssignmentHistList
.FirstOrDefault(i=>i.WeekOfAssignment==currentWeek&&i.TalkType==BIBLE\u READING\u TALK\u TYPE);
如果(啊!=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};
//使用ID获取该学生,并将他/她放入一人名单中(需要
//随后的LINQ联盟)
指定学生=
AyttfmConstandUtils.StudentsList.Where(i=>i.StudentID==ah.StudentID_FK).ToList();
}
}
//把所有的候选人都派出去
列出学生名单=
AyttfmConstandUtils.StudentsList.Where(h=>h.EnrolledAyttfm)
其中(i=>i.RecommendedNextTalkTypeID.Equals(圣经\阅读\谈话\类型))
.OrderBy(j=>j.weekofrastassignment)
.ToList();
如果(null!=已分配的学生)
{
列出所有BRStudents=assignedStudents.Union(BRStudents.ToList();
checkedListBoxBR.DataSource=所有BRStudents;
checkedListBoxBR.DisplayMember=“FullName”;
checkedListBoxBR.ValueMember=“StudentID”;
}
else//未找到指定学生,仅绑定到候选学生
{
checkedListBoxBR.DataSource=BRStudents;
checkedListBoxBR.DisplayMember=“FullName”;
checkedListBoxBR.ValueMember=“StudentID”;
}
//无论哪种情况,现在都突出显示并检查第一个
checkedListBoxBR.SelectedIndex=0;
checkedListBoxBR.SetItemChecked(0,true);
}

我发现有两件事不对

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

第二,你在比较苹果和桔子
checkedListBoxBR.Items
是对象的集合,您可以通过indexOf将其与字符串(
assignedStudent.FullName
)进行比较。那是行不通的

更好的解决方案是遍历
checkedListBoxBR.Items
,查看是否在项目的
DisplayMember
assignedStudent.FullName
之间找到匹配项


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

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

List<Student> BRStudents = [...]
checkedListBoxBR.DataSource = BRStudents;
此外,您可能希望

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

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

这可能是因为IndexOf在将对象绑定到BRStudents时需要一个对象。在循环中:“checkedListBoxBR.Items[i]”。索引i而不是0。并将removeAt应用于checkedListBoxBR.Items。我没有广泛使用Windows窗体,但请尝试
checkedListBoxBR.Items[I]。ToString()==assignedStudent.FullName
DisplayMember不是student的属性。强制转换为学生并使用全名。您需要在
之前的表达式周围添加括号。全名

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