【问题标题】:Multiple DataGridView from single DataSource来自单个数据源的多个 DataGridView
【发布时间】:2015-06-12 19:48:15
【问题描述】:

我有一个几乎可以工作的 Winform 应用程序,但在用户通过 DataGridViews 更新和插入数据的方式以及如何在后台将其反馈到 List 方面变得越来越复杂。目前,两个 DataGridView 都是从一个列表中填充的,当用户更新一个单元格时,列表会从网格中更新。我更喜欢将列表用作数据源。

非常简化的数据集(服务器、函数、过程) - P.S.我无法更改我的数据集:

Server1、KeepAlive、SQLService
Server1、KeepAlive、AnotherProcess
Server1、Kill、RogueProcess
Server2、KeepAlive、SQLService
Server3、KeepAlive、SQLService

DataGridView1 有 1 列包含不同的服务器名称,DataGridView2 有 2 列包含 DataGridView1 中所选服务器的所有功能和进程。用户可以编辑任何单元格,目前我会跟踪每个更改并将其反映回列表中,然后刷新网格。我更喜欢使用 DataGridView DataSource 对象来处理这个问题。

我的问题是:什么是最合适的数据源设置(即对象列表)?如何从不同的数据源过滤到 Grid 的?

到目前为止,我已经尝试了以下方法。创建一个 Config 类:

class Config
{
    [DisplayName("Server")]
    public string server { get; set; }

    [DisplayName("Function")]
    public string function { get; set; }

    [DisplayName("Process")]
    public string checkType { get; set; }
}

创建一个包含这些配置对象的列表:

List<Config> configurations = new List<Config>();

将列表指定为数据源:

dataGridView1.DataSource = configurations;

这将按预期显示所有三列数据。我如何 a) 只显示 Server 列和 b) 只显示一个不同的列表?

我猜测使用 DataGridView2 我可以使用 RowFilter 仅显示选定的服务器:

(dataGridView2.DataSource as DataTable).DefaultView.RowFilter = ?

提前感谢您的帮助!

编辑

我尝试过使用 LINQ:

dataGridView1.DataSource = configs.Select(o => new { Server = o.server }).ToList();

这可行,但我的网格是只读的,所以我也使用了自定义视图模型:

dataGridView1.DataSource = configs.Select(o => new ServerView() { Server = o.server }).ToList();

这正是我想要的显示方式,但是当我编辑单元格时,更改不会反映在列表中。 LINQ 可以像这样与 DataSource 一起使用吗?

编辑 2

使用 stefankmitph 的示例,我可以通过 SortableBindingList 进行过滤:

SortableBindingList<Config> sortableBindingList = new SortableBindingList<Config>(configs.Where(o => o.server == "Server1").ToList());
BindingSource bindingSource = new BindingSource(sortableBindingList, null);
dataGridView1.DataSource = bindingSource;

这解决了 DataGridView2 需要根据 #1 中选择的内容进行过滤的问题。但是,我仍然无法弄清楚如何只在网格中显示某些列。 #1 应该只有服务器,#2 应该有剩余的两列。 LINQ 查询中的选择不起作用,因为我正在处理一个 Config 对象......对吗?

【问题讨论】:

    标签: c# winforms datagridview


    【解决方案1】:

    多年来,我一直在与 DataGridView 的许多问题作斗争。这对我来说就是“最佳实践”:

    1a) 我经常将我的数据(列表)附加到一个 SortableBindingList(有很多示例 hereherehere。选择适合你的。)

    假设有一个列表配置;

    dataGridView.DataSource = new SortableBindingList<Config>(configurations);
    

    现在您的 DataGridView 可以排序了。

    1b) 在过滤数据源时,有很多选项。就我而言,过滤仅适用于将 DataTable 附加为 DataSource 的 BindingSource

    假设有一个DataTable dataTableConfigurations:

    BindingSource bindingSource = new BindingSource(dataTableConfigurations, null);
    dataGridView.DataSource = bindingSource;
    bindingSource.Filter = "Server = 'Server3'";
    

    但我很确定这不适用于作为数据源的对象列表。

    你可以做什么:

    SortableBindingList<Config> sortableBindingList = new SortableBindingList<Config>(configurations);
    BindingSource bindingSource = new BindingSource(sortableBindingList, null);
    dataGridView.DataSource = bindingSource;
    

    这样可以很容易地跟踪数据的变化。 (例如 BindingSource.Current 返回 DataGridView 的当前项)

    BindingSource bindingSource = dataGridView.DataSource as BindingSource;
    Config currentConfig = bindingSource.Current as Config;
    

    如果我现在必须过滤数据,我会执行以下操作:

    BindingSource bindingSource = dataGridView.DataSource as BindingSource;
    List<Config> list = bindingSource.DataSource as List<Config>;
    bindingSource.DataSource = list.Where(item => item.Server = 'banana').ToList();
    

    如果您对 BindingSource(文本框、组合框等)有任何绑定,请记住附加/分离 DataSource 可能会导致不需要的行为。为避免这种情况,我会暂停和恢复绑定:

    bindingSource.SuspendBinding();
    // do the filtering
    bindingSource.ResumeBinding();
    

    这使所有 DataBindings 保持活动状态。

    更新:仅在 DataGridView 中显示某些列

    这很简单。 (列名与 DataSource 对象中的名称相关)

    var columnFunction = dataGridView.Columns["function"];
    if(columnFunction != null)
        columnFunction.Visible = false;
    
    var columnCheckType = dataGridView.Columns["checkType"];
    if(columnCheckType != null)
        columnCheckType.Visible = false;
    

    所以只会显示您的服务器列。

    【讨论】:

    • 感谢您的回答。请参阅我的编辑 2 - 基本上绑定确实按照您的详细说明工作,但我仍然无法弄清楚如何在网格中仅显示某些列。
    猜你喜欢
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多