C#中相关的DataGridView

问题描述 投票:0回答:2

我的表单中有两个 Datagridview,其中一个显示“作者”(姓名)列表,另一个显示书籍列表(书名、作者、年份、价格)。 在表单加载中,它显示所有书籍,但我希望当用户单击第一个 datagridview 上的作者姓名时,第二个 datagridview 中的数据更新并仅显示与所选作者相关的书籍。

作者列表的第一个字段应该是“ALL”,这样用户即使在按作者过滤后也能够列出所有书籍。

抱歉我的英语不好

c# winforms datagridview
2个回答
0
投票

使用datagridview1 c#的Cellclick事件

获取作者作者列的单元格值

那么你应该按作者搜索书籍(也许有列表)

然后将List设置为datagridview2的DataSource


0
投票

所以在内部你有

Authors
Books
的集合。不知何故,可能通过外键,作者和书籍之间存在链接:如果您有一个作者,您可以获取他所有的书籍,反之,如果您有一本书,您可以获取他的作者。

你的课程

课程将类似于以下内容:

class Author
{
    public int Id {get; set;}
    public string Name {get; set;}
    ... // other properties, Birthday? Bankaccount? Address?

    // Every Author has written zero or more Books
    public virtual ICollection<Book> Books {get; set;}
}

class Book
{
    public int Id {get; set;}
    public string Title {get; set;}
    public DateTime PublicationDate {get; set;}
    public decimal Price {get; set;}

    // every Book is written by exactly one Author, using foreign key
    public int AuthorId {get; set;}
    public virtual Author Author {get; set;}
}

这些类看起来与使用实体框架时拥有的类非常相似。但是,数据库表不会有虚拟函数。如果不使用实体框架,则必须自己编写虚拟函数。考虑将它们添加为扩展方法。这样您就可以使您的课程与您的表格保持相似。如果您不熟悉扩展方法,请阅读扩展方法揭秘

您的表格

使用设计器,您添加了两个 DataGridView,一个将显示所有作者的一些属性,另一个将显示所选作者撰写的书籍的一些属性。

使用设计器,您还添加了要在 DataGridView 中显示的列。

使用属性 DataGridViewColumn.DataPropertyName 您可以定义哪个列将显示哪个属性。您可以使用设计器来执行此操作,我更喜欢在表单的构造函数中执行此操作。

class MyForm
{
    public MyForm()
    {
        this.InitializeComponents();

        // Define which column should show which Author properties:
        columnAuthorsName.DataPropertyName = nameof(Author.Name);
        // if needed, add other columns, for example:
        columnAuthorsBirthDay.DataPropertyName = nameof(Author.BirthDay);

        // Do the same for the Books:
        columnBooksTitle.DataPropertyName = nameof(Book.Title);
        columnBooksPrice.DataPropertyName = nameof(Book.Price);
        ...
   

您的表单需要一些方法来从数据库中获取作者和书籍:

public IEnumerable<Author> GetAllAuthors();
public IEnumerable<Book> GetBooksOfAuthor(int authorId);

实施取决于您存储作者和书籍的方式。我会让你来实施。

获取和设置 DataGridView 内容的属性:

public BindingList<Author> DisplayedAuthors
{
    get => (BindingList<Author>)this.DataGridViewAuthors.DataSource;
    set => this.DataGridViewAuthors.DataSource = value;
}

public BindingList<Book> DisplayedBooks
{
    get => (BindingList<Book>)this.DataGridViewBooks.DataSource;
    set => this.DataGridViewBooks.DataSource = value;
}

最初显示所有作者,但不显示书籍(尚未选择任何作者):

public void InitializeDataGridViews()
{
    this.DisplayedAuthors = new BindingList<Author>(this.GetAllAuthors().ToList());
    this.DisplayedBooks = null;   // it might be that you need to assign empty array
}

获取选定的作者和选定的书籍

显然您需要属性来获取选定的作者。当我向表单添加 DataGridView 时,我总是添加以下两个属性:

public IEnumerable<Author> SelectedAuthors => this.DataGridViewAuthors.SelectedRows
    .Cast<DataGridViewColumn>()
    .Select(row => row.DataBoundItem)
    .Cast<Author>();

换言之:要获取所有 SelectedAuthors(可能不止一个),请从 DataGridViewAuthors 获取所有 SelectedRow。将其转换为 DataGridViewRows 序列。从每个 DataGridViewRow 获取其 DataBoundItem 的值。因为我只使用 DisplayedAuthors 属性来显示作者,所以我知道每个 DataBoundItem 都是一个作者,因此我可以将每个获取的 DataBoundItem 转换为一个作者。

我还需要一个属性来获取当前作者:

public Author CurrentAuthor => (Author)this.DataGridViewAuthors.CurrentRow.DataBoundItem;

对于书籍我也可以这样做:

public IEnumerable<Author> SelectedBooks => this.DataGridViewBooks.SelectedRows
    .Cast<DataGridViewColumn>()
    .Select(row => row.DataBoundItem)
    .Cast<Book>();

public Author CurrentBook => 
    (Book)this.DataGridViewBooks.CurrentRow.DataBoundItem;

选择作者后显示作者书籍

上面看起来代码很多。然而,所有的方法和属性都只是一两行代码。它们易于理解、易于更改和维护、易于重用且易于进行单元测试。

显示所选作者的书籍的所有这些属性也可以写在一行中。为了便于理解,我将其分为三行:

public void DisplayBooksOfSelectedAuthor()
{
    Author selectedAuthor = this.SelectedAuthor;
    IEnumerable<Book> booksOfSelectedAuthor = this.GetBooksOfAuthor(selectedAuthor.Id);
    this.DisplayedBooks = new BindingList<Book>(booksOfSelectedAuthor.ToList());
}

快到了

订阅事件 DataGridView.SelectionChanged

public void OnDataGridViewAuthorSelectionChanged(object sender, ...)
{
    this.DisplayBooksOfSelectedAuthor();
}

单线方法,现在这应该不足为奇。

总结

  • 不要直接修改行和单元格的内容。使用数据绑定
  • 使用属性获取和设置显示的作者和书籍
  • 使用属性获取选定的作者和书籍
  • 使用方法获取所有作者以及某个作者的所有书籍

这些方法都非常小,易于理解,易于维护和更改,易于重用和单元测试。

© www.soinside.com 2019 - 2024. All rights reserved.