winforms 使用从表单1到表单3的列表框对象项更新所述对象属性

lb3vh1jj  于 2022-11-16  发布在  其他
关注(0)|答案(2)|浏览(155)

我有一个主窗体,其中的列表框包含具有姓名和三个分数的学生对象。我想在新窗体中用新分数更新所选列表框的学生对象。我似乎无法引用或抓取selecteditem对象以使其显示在新窗体中。
//新表单中的代码,加载新表单时返回空值

Form1 frm = new Form1(); 
Student currentStudent = (Student)frm.listBox.SelectedItem;
  if (currentStudent != null)
  {
     txtName.Text = currentStudent.Name;
  }

//form 1中的代码

private void btnUpdate_Click(object sender, EventArgs e)
{
  using(Form3 frm = new Form3())
  {
    DialogResult button = frm.ShowDialog();
               
  }           
}
r6vfmomb

r6vfmomb1#

我重现了你的问题。
列表框控件绑定到数据源。

private void button1_Click(object sender, EventArgs e)
     {
         this.listBox1.Items.Clear();

         // create data
         List<Student> students = new List<Student>();
         students.Add(new Student() { Name = "admin", Engrade = 78, Magrade = 88, Clugrade = 89});
         students.Add(new Student() { Name = "tony", Engrade = 75, Magrade = 77, Clugrade = 84 });
         students.Add(new Student() { Name = "lucy", Engrade = 85, Magrade = 67, Clugrade = 69});

         // bind data without modifying the binding
         this.listBox1.DataSource = students;
         this.listBox1.DisplayMember = "Name"; // Properties of display content data
         this.listBox1.ValueMember = "Engrade";// item value attribute of data
     }

获取当前选定内容的值。

private void button2_Click(object sender, EventArgs e)
     {
         // selection item collection of items
         var items = this.listBox1.SelectedItems;
         string strItem = "";

         foreach(var item in items)
         {
             Student stu1 = (Student)item;
             if (stu1 != null)
             {
                 strItem += stu1.Name.ToString() + ",";
             }
            // strItem += stu1.Name.ToString() + ",";
         }

         textBox1.Text = strItem;

         StuName.Name = strItem;

     }

打开新表单

private void button3_Click(object sender, EventArgs e)
    {
        using (Form2 frm = new Form2())
        {
            DialogResult button = frm.ShowDialog();
            
        }
    }

    private void Form2_Load(object sender, EventArgs e)
    {
       textBox1.Text = StuName.Name.ToString();
    }

检测项目

niwlg2el

niwlg2el2#

我建议使用事件将更改从子窗体推送到主窗体。

学生类

public class Student
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public decimal Score { get; set; }
    public override string ToString() => $"{FirstName} {LastName}";
}

模拟一些数据

public class Operations
{
    public static List<Student> Students()
    {
        return new List<Student>()
        {
            new Student() {Id = 1, FirstName = "Jim", LastName = "Adams", Score = 87m},
            new Student() {Id = 2, FirstName = "Mary", LastName = "Jones", Score = 73m},
        };
    }
}

主窗体,注意我们订阅子窗体中的自定义事件。BindingSource连接到ListBox,其中BindingSource数据源来自Student的BindingList。

using System.ComponentModel;

namespace StackoverflowApp
{
    public partial class Form1 : Form
    {
        private readonly BindingSource _bindingSource = new BindingSource();
        private BindingList<Student> _bindingList = new BindingList<Student>();

        public Form1()
        {
            InitializeComponent();
            
            Shown += OnShown;
        }

        private void OnShown(object sender, EventArgs e)
        {
            _bindingList = new BindingList<Student>(Operations.Students());
            _bindingSource.DataSource = _bindingList;
            listBox1.DataSource = _bindingSource;
        }

        private void ShowFormButton_Click(object sender, EventArgs e)
        {
            using ChildForm form = new ChildForm(_bindingList[_bindingSource.Position]);
            form.OnStudentChanged += FrmOnOnStudentChanged;
            form.ShowDialog();
            form.OnStudentChanged -= FrmOnOnStudentChanged;
        }

        private void FrmOnOnStudentChanged(Student student)
        {
            _bindingList[_bindingSource.Position] = student;
            _bindingList.ResetItem(_bindingSource.Position);
        }

        private void CurrentButton_Click(object sender, EventArgs e)
        {
            var student = _bindingList[_bindingSource.Position];
            MessageBox.Show($"{student.Id}, {student.FirstName}, {student.LastName}, {student.Score}");
        }
    }
}

子窗体从构造函数中获取student,将其赋值给一个私有var,该var又是窗体上控件的数据绑定。

namespace StackoverflowApp
{
    public partial class ChildForm : Form
    {
        public delegate void StudentUpdate(Student student);
        public event StudentUpdate OnStudentChanged;
        private readonly Student _student;

        public ChildForm()
        {
            InitializeComponent();
        }
        public ChildForm(Student student)
        {
            InitializeComponent();

            _student = student;

            FirstNameTextBox.DataBindings.Add(
                "Text", student, nameof(Student.FirstName));
            LastNameTextBox.DataBindings.Add(
                "Text", student, nameof(Student.LastName));
            ScoreNumericUpDown.DataBindings.Add(
                "Value", student, nameof(Student.Score));

        }

        private void UpdateButton_Click(object sender, EventArgs e)
        {
            // TODO - Validation
            OnStudentChanged?.Invoke(_student);
        }
    }
}

在将数据发送回主窗体之前,应考虑在子窗体中添加验证。在将数据发送到子窗体之前,还可以检查是否选择了当前项目。
请注意,在所提供的代码中,ListBox仅被引用一次,用户应仅在绝对必要时接触控件,而不是使用组件,例如BindingSource、BindingList。

相关问题