在级联 CheckedListBox 中保留项目的检查状态
Preserve check state of the items in cascading CheckedListBox
我的 C# windows 表单应用程序中有 2 个 Checkedlistbox
控件。第一个 Checkedlistbox
是医生的专业,例如牙医、放射科医生等。如果我选中牙医复选框医生的专业 Checkedlistbox
控件,所有牙医都会显示在医生的名字中 Checkedlistbox
控制.
问题是,当我检查牙医 Checkedlistbox
然后医生 Checkedlistbox
的一些牙医时,如果我检查放射科医生 Checkedlistbox
,那么医生的名字 Checkedlistbox
将被重置并且我的牙医检查的所有复选框都将被取消选择。
我试过的:
医生姓名Checkedlistbox
数据来源:
DoctorsIDCheckedlistbox.DataSource = _ClinicEntities.Tbl_Doctors
.Where(w => _SelectedSpecialty.Contains(w.SpecialtyID))
.Select(s => new DoctorListCheckbox{ Name = s.Name + " " + s.LastName, DoctorID = s.DoctorID })
.ToList();
DoctorsIDCheckedlistbox.DisplayMember = "Name";
DoctorsIDCheckedlistbox.ValueMember = "DoctorID";
然后我在ItemCheck
事件中保存选中的项目:
private void DoctorsID_ItemCheck(object sender, ItemCheckEventArgs e)
{
int doctorID = Convert.ToInt32(DoctorsIDCheckedlistbox.SelectedValue);
if (e.NewValue == CheckState.Checked)
{
_SelectedDoctorsChecked.Add(doctorID.ToString());
}
else
{
_SelectedDoctorsChecked.Remove(doctorID.ToString());
}
}
然后医生专业ItemCheck
事件:
private void SpecialtyTypeID_ItemCheck(object sender, ItemCheckEventArgs e)
{
for (int i = 0; i < DoctorsIDCheckedlistbox.Items.Count; i++)
{
if (_SelectedDoctorsChecked.Contains(DoctorsIDCheckedlistbox.Items[i].ToString()))
{
try
{
DoctorsIDCheckedlistbox.SetItemChecked(i, true);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
我希望上面的代码查看选定医生的 _SelectedDoctorsChecked
列表,并在医生的专业复选框状态更改时检查它们。但它不起作用。
示例:
我在医生的专业中勾选A,第1、2、3项将显示在医生的姓名中。我检查 1 和 3。当我检查医生专业中的 B 时,将显示 A 中的项目 1、2 和 3 以及 B 中的 4、5 和 6。我希望检查 1 号和 3 号。但是不会。
编辑:
我的Checkedlistbox
控件数据源:
DoctorsIDCheckedlistbox.DataSource = _ClinicEntities.Tbl_Doctors
.Where(w => _SelectedSpecialty.Contains(w.SpecialtyID))
.Select(s => new DoctorListCheckbox{ Name = s.Name + " " + s.LastName, DoctorID = s.DoctorID })
.ToList();
DoctorsIDCheckedlistbox.DisplayMember = "Name";
DoctorsIDCheckedlistbox.ValueMember = "DoctorID";
和DoctorListCheckbox
class:
public partial class DoctorListCheckbox
{
public int DoctorID { get; set; }
public string Name { get; set; }
public CheckState CheckState { get; set; }
public override string ToString()
{
return Name;
}
}
做的
基本原理和我在中解释的一样。
您需要定义一个BindingList<Specialties>
作为专业检查列表框的数据源并显示所有专业。
对于医生,您需要一个空的BindingList<CheckedListBoxItem<Doctor>>
并将其设置为医生检查列表框的数据源。那么你需要处理以下事件:
ItemChecked
专业检查列表框事件:如果项目被选中,则从您的存储库中找到所有具有检查专业的医生,并将他们作为 CheckedListBoxItem<Doctor>
绑定列表。否则,在绑定源中找到所有未勾选专业的医生,将其移除。
ItemChecked
医生事件:使用选中列表框项的选中状态同步绑定列表项的选中状态。
ListChanged
绑定列表事件:同步勾选列表框项勾选状态,使用绑定列表项勾选状态。
例子
这是一个场景的完整示例,该场景具有 2 个选中的专业和医生列表框以及 select 医生基于 selected 专业:
型号
public class Speciality
{
public int Id { get; set; }
public string Name { get; set; }
public override string ToString() { return Name; }
}
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public int SpecialityId { get; set; }
public override string ToString() { return Name; }
}
public class CheckedListBoxItem<T>
{
public CheckedListBoxItem(T item)
{
DataBoundItem = item;
}
public T DataBoundItem { get; set; }
public CheckState CheckState { get; set; }
public override string ToString() { return DataBoundItem.ToString(); }
}
示例数据
public class DB
{
public IEnumerable<Speciality> Specialities
{
get
{
return new List<Speciality>()
{
new Speciality(){ Id= 1, Name ="S1"},
new Speciality(){ Id= 2, Name ="S2"},
new Speciality(){ Id= 3, Name ="S3"},
};
}
}
public IEnumerable<Doctor> Doctors
{
get
{
return new List<Doctor>()
{
new Doctor(){ Id= 1, Name ="D1", SpecialityId = 1},
new Doctor(){ Id= 2, Name ="D2", SpecialityId = 2},
new Doctor(){ Id= 3, Name ="D3", SpecialityId = 2},
new Doctor(){ Id= 4, Name ="D4", SpecialityId = 3},
new Doctor(){ Id= 5, Name ="D5", SpecialityId = 3},
new Doctor(){ Id= 6, Name ="D6", SpecialityId = 3},
};
}
}
}
表单事件处理程序
DB db = new DB();
BindingList<Speciality> specialities;
BindingList<CheckedListBoxItem<Doctor>> doctors;
private void Form10_Load(object sender, System.EventArgs e)
{
specialities = new BindingList<Speciality>(db.Specialities.ToList());
specialitiesCheckedListBox.DataSource = specialities;
doctors = new BindingList<CheckedListBoxItem<Doctor>>();
doctorsCheckedListBox.DataSource = doctors;
doctors.ListChanged += doctors_ListChanged;
}
private void doctors_ListChanged(object sender, ListChangedEventArgs e)
{
for (var i = 0; i < doctorsCheckedListBox.Items.Count; i++) {
doctorsCheckedListBox.SetItemCheckState(i,
((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[i]).CheckState);
}
}
private void specialitiesCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
var item = (Speciality)specialitiesCheckedListBox.Items[e.Index];
if (e.NewValue == CheckState.Checked) {
db.Doctors.Where(x => x.SpecialityId == item.Id)
.Select(x => new CheckedListBoxItem<Doctor>(x)).ToList()
.ForEach(x => doctors.Add(x));
}
else {
doctors.Where(x => x.DataBoundItem.SpecialityId == item.Id)
.ToList().ForEach(x => doctors.Remove(x));
}
}
private void doctorsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[e.Index])
.CheckState = e.NewValue;
}
我的 C# windows 表单应用程序中有 2 个 Checkedlistbox
控件。第一个 Checkedlistbox
是医生的专业,例如牙医、放射科医生等。如果我选中牙医复选框医生的专业 Checkedlistbox
控件,所有牙医都会显示在医生的名字中 Checkedlistbox
控制.
问题是,当我检查牙医 Checkedlistbox
然后医生 Checkedlistbox
的一些牙医时,如果我检查放射科医生 Checkedlistbox
,那么医生的名字 Checkedlistbox
将被重置并且我的牙医检查的所有复选框都将被取消选择。
我试过的:
医生姓名Checkedlistbox
数据来源:
DoctorsIDCheckedlistbox.DataSource = _ClinicEntities.Tbl_Doctors
.Where(w => _SelectedSpecialty.Contains(w.SpecialtyID))
.Select(s => new DoctorListCheckbox{ Name = s.Name + " " + s.LastName, DoctorID = s.DoctorID })
.ToList();
DoctorsIDCheckedlistbox.DisplayMember = "Name";
DoctorsIDCheckedlistbox.ValueMember = "DoctorID";
然后我在ItemCheck
事件中保存选中的项目:
private void DoctorsID_ItemCheck(object sender, ItemCheckEventArgs e)
{
int doctorID = Convert.ToInt32(DoctorsIDCheckedlistbox.SelectedValue);
if (e.NewValue == CheckState.Checked)
{
_SelectedDoctorsChecked.Add(doctorID.ToString());
}
else
{
_SelectedDoctorsChecked.Remove(doctorID.ToString());
}
}
然后医生专业ItemCheck
事件:
private void SpecialtyTypeID_ItemCheck(object sender, ItemCheckEventArgs e)
{
for (int i = 0; i < DoctorsIDCheckedlistbox.Items.Count; i++)
{
if (_SelectedDoctorsChecked.Contains(DoctorsIDCheckedlistbox.Items[i].ToString()))
{
try
{
DoctorsIDCheckedlistbox.SetItemChecked(i, true);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
我希望上面的代码查看选定医生的 _SelectedDoctorsChecked
列表,并在医生的专业复选框状态更改时检查它们。但它不起作用。
示例:
我在医生的专业中勾选A,第1、2、3项将显示在医生的姓名中。我检查 1 和 3。当我检查医生专业中的 B 时,将显示 A 中的项目 1、2 和 3 以及 B 中的 4、5 和 6。我希望检查 1 号和 3 号。但是不会。
编辑:
我的Checkedlistbox
控件数据源:
DoctorsIDCheckedlistbox.DataSource = _ClinicEntities.Tbl_Doctors
.Where(w => _SelectedSpecialty.Contains(w.SpecialtyID))
.Select(s => new DoctorListCheckbox{ Name = s.Name + " " + s.LastName, DoctorID = s.DoctorID })
.ToList();
DoctorsIDCheckedlistbox.DisplayMember = "Name";
DoctorsIDCheckedlistbox.ValueMember = "DoctorID";
和DoctorListCheckbox
class:
public partial class DoctorListCheckbox
{
public int DoctorID { get; set; }
public string Name { get; set; }
public CheckState CheckState { get; set; }
public override string ToString()
{
return Name;
}
}
做的
基本原理和我在
您需要定义一个BindingList<Specialties>
作为专业检查列表框的数据源并显示所有专业。
对于医生,您需要一个空的BindingList<CheckedListBoxItem<Doctor>>
并将其设置为医生检查列表框的数据源。那么你需要处理以下事件:
ItemChecked
专业检查列表框事件:如果项目被选中,则从您的存储库中找到所有具有检查专业的医生,并将他们作为CheckedListBoxItem<Doctor>
绑定列表。否则,在绑定源中找到所有未勾选专业的医生,将其移除。ItemChecked
医生事件:使用选中列表框项的选中状态同步绑定列表项的选中状态。ListChanged
绑定列表事件:同步勾选列表框项勾选状态,使用绑定列表项勾选状态。
例子
这是一个场景的完整示例,该场景具有 2 个选中的专业和医生列表框以及 select 医生基于 selected 专业:
型号
public class Speciality
{
public int Id { get; set; }
public string Name { get; set; }
public override string ToString() { return Name; }
}
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public int SpecialityId { get; set; }
public override string ToString() { return Name; }
}
public class CheckedListBoxItem<T>
{
public CheckedListBoxItem(T item)
{
DataBoundItem = item;
}
public T DataBoundItem { get; set; }
public CheckState CheckState { get; set; }
public override string ToString() { return DataBoundItem.ToString(); }
}
示例数据
public class DB
{
public IEnumerable<Speciality> Specialities
{
get
{
return new List<Speciality>()
{
new Speciality(){ Id= 1, Name ="S1"},
new Speciality(){ Id= 2, Name ="S2"},
new Speciality(){ Id= 3, Name ="S3"},
};
}
}
public IEnumerable<Doctor> Doctors
{
get
{
return new List<Doctor>()
{
new Doctor(){ Id= 1, Name ="D1", SpecialityId = 1},
new Doctor(){ Id= 2, Name ="D2", SpecialityId = 2},
new Doctor(){ Id= 3, Name ="D3", SpecialityId = 2},
new Doctor(){ Id= 4, Name ="D4", SpecialityId = 3},
new Doctor(){ Id= 5, Name ="D5", SpecialityId = 3},
new Doctor(){ Id= 6, Name ="D6", SpecialityId = 3},
};
}
}
}
表单事件处理程序
DB db = new DB();
BindingList<Speciality> specialities;
BindingList<CheckedListBoxItem<Doctor>> doctors;
private void Form10_Load(object sender, System.EventArgs e)
{
specialities = new BindingList<Speciality>(db.Specialities.ToList());
specialitiesCheckedListBox.DataSource = specialities;
doctors = new BindingList<CheckedListBoxItem<Doctor>>();
doctorsCheckedListBox.DataSource = doctors;
doctors.ListChanged += doctors_ListChanged;
}
private void doctors_ListChanged(object sender, ListChangedEventArgs e)
{
for (var i = 0; i < doctorsCheckedListBox.Items.Count; i++) {
doctorsCheckedListBox.SetItemCheckState(i,
((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[i]).CheckState);
}
}
private void specialitiesCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
var item = (Speciality)specialitiesCheckedListBox.Items[e.Index];
if (e.NewValue == CheckState.Checked) {
db.Doctors.Where(x => x.SpecialityId == item.Id)
.Select(x => new CheckedListBoxItem<Doctor>(x)).ToList()
.ForEach(x => doctors.Add(x));
}
else {
doctors.Where(x => x.DataBoundItem.SpecialityId == item.Id)
.ToList().ForEach(x => doctors.Remove(x));
}
}
private void doctorsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[e.Index])
.CheckState = e.NewValue;
}