winforms 如何在Windows窗体中单击DataGridView中的数据时自动填充窗体

iyzzxitl  于 2023-08-07  发布在  Windows
关注(0)|答案(2)|浏览(136)

我想让表单文本框在我单击表单中给定的DataGridView中的数据时自动填充。
The Form IMG
我希望动态文本框自动填充,即。我想把数据从DataGridView传递到活动的文本框,但我不知道如何做到这一点。在网上没有找到任何有帮助的东西,或者我可能没有说对。任何解决方案都可以,我不需要整个代码,只是它的概念,或者一些伪代码就可以了。P.S.我使用了MS Access数据库。

gg58donl

gg58donl1#

好的,WinForms在设计视图中有一个属性,名为CellContentClickCellContentDoubleClick的事件在调用时调用特定的事件。因此,当我在事件中添加以下代码后双击数据中的单元格或元素时:-

{
            if (e.RowIndex != -1) 
            {
                DataGridViewRow row = dataGridViewUsers.Rows[e.RowIndex];
                //ID
                txtUsersUID.Text = row.Cells[0].Value.ToString();
                //Username
                txtUsersFirstname.Text = row.Cells[1].Value.ToString();
                //Password
                txtUsersPassword.Text = row.Cells[2].Value.ToString();
            }
        }

字符串
然后获取行的指定单元格的值,例如:-Selected Cell of a DataGridView,然后将文本传递到指定的文本框:-
output of the code

x33g5p2x

x33g5p2x2#

好的,你有一个Persons的集合,其中每个Person都有几个属性。您还有一个DataGridView,它显示了您的集合中人物的IdUserName
每当操作员按一下DataGridView的其中一个数据列时,您就会想要在文字方块中显示Person的其他属性值。

数据与其显示方式的分离

在使用DataGridView时,人们往往会直接处理行、列和单元格的内容。
几年来,数据(=模型)与其显示方式(=视图)有分离的趋势。这样做的主要优点是,您可以更改视图,而不必更改模型。您也可以变更“模型”,而不必变更其显示方式。
例如,如果有一个Sales的列表,其中每个Sale在该日期都有一个Date和一个Total的销售额,则可以在表/ DataGridView中显示此列表,但也可以决定在图表中显示此列表,而不必更改销售额列表。
另一方面,如果将来要将列表更改为数据库,Model和View的分离可以确保您不必为此更改View。
要将Model与View连接起来,需要一个适配器类,称为ViewModel。这三个类别统称为MVVM。如果您不熟悉此概念,请考虑阅读一些有关MVVM的背景信息。

您的数据网格视图和MVVM

所以你有一个Persons的集合。类Person将类似于以下内容:

class Person
{
    public int Id {get; set;}
    public string UserName {get; set;}
    public string FirstName {get; set;}
    ...
}

字符串
您的表单具有方法,可撷取必须显示的人员集合:

public IEnumerable<Person> GetPersonsToDisplay() {...};


我将把实现留给您。毕竟你知道你从哪里得到你的人:从文本文件、数据库或可能从因特网。
在Windows设计工具中,您已将DataGridView和数据行加入至表单。这是使用属性DataGridViewColumn.DataPropertyName来完成的。您也可以使用设计工具来指定这个属性的值。我更喜欢在Form的建构函式中完成这项工作。

public MyForm()
{
    InitializeComponents();

    // define which property is shown in which column:
    this.ColumnId.DataPropertyName = nameof(Person.Id);
    this.ColumnUserName.DataPropertyName = nameof(Person.UserName);
    ... // etc, if in future you want to show more Person properties in your DataGridView


此方法的优点是,如果将来您决定更改属性而忘记更改构造函数,则编译器会发出警告。
要显示人员列表,只需一行代码即可:

this.DgvPersons.DataSource = this.GetPersonsToDisplay.ToList();


然后,所有的人都会显示在DataGridView中。
但是,人们通常希望能够编辑表的内容。他们希望在操作员指示他已完成编辑后自动更新。这也可以使用BindingList在几行代码中完成

public BindingList<Person> DisplayedPersons
{
    get => (BindingList<Person>)this.DgvPersons.DataSource;
    set => this.DgvPersons.DataSource = value;
}


同样,初始化DataGridView是一行代码:

this.DisplayedPersons = new BindingList<Person>(this.GetPersonsToDisplay.ToList());


现在,假设操作员已经编辑了该表,并按下Apply Now按钮以指示他已经完成了编辑。为此按钮添加事件处理程序:

public void OnButtonApplyNow_Clicked(object sender, ...)
{
    ICollection<Person> editedPersons = this.DisplayedPersons;
    this.ProcessEditedPersons(editedPersons);
}


ProcessEditedPersons方法可以将原始Persons与editedPersons进行比较,找出删除的Persons、添加的Persons和更改的Persons,并进行相应的操作。实作超出此问题的范围。
最后还有两个不错的特性:

public Person CurrentPerson => (Person)this.DgvPersons.CurrentRow.DataBoundItem;
    
public IEnumerable<Person> SelectedPersons => this.DgvPersons.SelectedRows
    .Cast<DataGridViewRow>()
    .Select(row => row.DataBoundItem)
    .Cast<Person>();


顺便说一句,我不喜欢将所有内容都转换为List。首先,如果只使用List的前几个元素,将是对处理能力的极大浪费。此外,如果您实现了对DataGridView进行排序,则不会定义所获得的Persons的顺序; Person[4]不会有一个有意义的定义含义。如果调用者的属性需要一个Collection或一个List,它们可以做ToList。
上述属性可用于任何数据网格视图。模型与视图完全分离。我所描述的方法是ViewModel。对于小窗体,只需将这些方法添加到窗体中即可。如果您希望能够在其他表单中重复使用它们,请考虑创建一个单独的ViewModel类。
回到你的问题上
现在您已经将模型与视图分离,所选Person的属性显示很简单:

void DisplayPerson(Person Person)
{
    this.TextBoxUserId.Text = person.Id.ToString();
    this.TextBoxUserFirstName.Text = sperson.FirstName;
    this.TexBoxLastName.Text = person.LastName;
    ...
}


您所要做的就是为DataGridView.CurrentCellChanged添加一个事件处理程序。同样,在所有工作(在所有这些单行方法之后)之后,这是一行代码:

public void OnPersonsTable_CurrentCellChanged(object sender, ...)
{
    this.DisplayPerson(this.SelectedPerson)
    // TODO: optimization if Person already is displayed
}


注意:如果您使用方向键或Page Up / Page Down / Home / End逐步浏览表格,也可以使用此功能。如果你不想这样,甚至订阅CellClicked。找出点击了哪个单元格,找出该单元格所在的行,得到DataBoundItem:

public Person GetPerson(DataGridViewRow row)
{
    return (Person)row.DataBoundItem;
}

public void OnPersonsTable_CellClicked(object sender, DataGridViewCellEventArgs e)
{
    DataGridViewRow clickedRow = this.DgvPersons.Rows[e.RowIndex];
    Person clickedPerson = this.GetPerson(clickedRow);
    this.DisplayPerson(clickedPerson);
}


当然,如果你愿意,你可以在一行中完成。代码的效率不会提高多少,但可读性会下降。

摘要

通过将模型与视图分离,您不再需要直接处理单元格和行。
通过仅添加几个属性,您可以访问完整的人员集合、所选人员或仅当前人员。这些属性都非常小,使用它们通常也只需要几行代码。

相关问题