【问题标题】:How to make All cells of a datagridview editable如何使datagridview的所有单元格可编辑
【发布时间】:2021-11-15 06:13:55
【问题描述】:

我正在开发一个 c# windows 窗体项目,一旦获得焦点,我必须在编辑模式下打开 datagridview 的所有单元格。但我不知道该怎么做。我是 C# 新手。

【问题讨论】:

  • EditMode = EditOnEnter.
  • 谢谢吉米。这解决了我的问题。但我还有另一个问题。如何将焦点设置在第一行和第一列的第一个单元格上

标签: winforms datagridview c#-2.0


【解决方案1】:

MVVM

不熟悉 DataGridView 编程的程序员在读取和写入值时往往会直接摆弄单元格。虽然这可行,但效率不高:您的代码将难以阅读、难以调试、难以更改和难以调试。

在现代编程中,倾向于将数据(= 模型)与向操作员呈现数据的方式(= 视图)分开。适配器类,通常称为 ViewModel,用于将模型连接到视图。这三个类一起缩写为 MVVM。考虑阅读一些关于此的背景信息。

将模型与视图分离的好处之一是,您可以更改视图而无需更改模型:如果您想在图表而不是表格中显示数据,您的数据不会必须改变。或者,如果您想在数据中添加额外的列,但您不需要显示它们,则您的视图不必更改。同样:如果您打算从文件而不是数据库中获取数据:视图中没有变化。

将模型与视图分离的其他优点是,您可以在显示数据其他方面的表单中重用模型,您可以在不使用表单的情况下对模型进行单元测试,在开发过程中您可以模拟模型,以在没有真实数据的情况下显示您的表单。

MVVM 和 DataGridView

唉,您没有指定要在 DataGridView 中显示的内容,因此假设您要显示 Products 的表格:

型号

class Product
{
    public int Id {get; set;}
    public string Name {get; set;}
    public string Description {get; set;}
    public decimal Price {get; set;}
    public int StockCount {get; set;}

    public int LocationId {get; set;}  // foreign key to location
    ...
}

当然,您的模型需要一个过程来获取必须显示的产品:

class MyModel
{
    IEnumerable<Product> FetchProducts()
    {
        // TODO implement; out of scope of the question
    }

    ... // other Model methods
}

所以在模型中,您不会有与数据显示方式有任何关系的方法。

视图模型

假设,在此特定表单(此视图)上,您不想显示所有产品,而只想显示缺货的产品。这是将模型耦合到视图的典型适配器方法

class MyViewModel
{
    private MyModel Model => ...

    IEnumerable<Product> FetchOutOfStockProducts()
    {
        return this.Model.FetchProducts()
            .Where(product => product.StockCount == 0);
    }
}

如果以后您不想展示完全缺货的产品,但又想展示几乎缺货的产品,您只需更改此程序(并且也许是名字,为了更好的可读性)。

如果您真的想将模型与视图分开,请考虑创建一个类DisplayedProduct,该类内部包含一个Product。这使您有机会添加或隐藏产品的属性。将来您可以更改产品,而无需更改使用该产品的 20 种表格。您可以创建在内部使用产品以外的其他东西的 DisplayedProducts。或者如果你想添加一个属性:

public decimal TotalStockValue => this.Product.StockCount * this.Product.Price;

您是否需要创建 DisplayedProduct 类取决于显示的数据与您的模型有多少不同、您认为产品会改变的频率、产品在不同表单上显示的频率以及您期望视图的频率改变。

观点

这是有趣的部分。使用 Visual Studio 设计器,您添加了 DataGridView 和列。您需要告诉 DataGridView 哪一列应该显示 Product 的哪个值。

您也可以使用 Visual Studio 设计器执行此操作。如果您想确保在输入错误时编译器会抱怨,请在构造函数中执行以下操作:

public MyForm()
{
    InitializeComponent();

    // define which columns should show which properties of Product:
    this.columnId.DataPropertyName = nameof(Product.Id);
    this.columnName.DataPropertyName = nameof(Product.Name);
    this.columnPrice.DataPropertyName = nameof(Product.Price);

    ... // etc.

当然,对于无论如何都不会显示的值,您不需要列。模型和视图分离的另一个优点:如果将来在您不需要显示的列中添加了一个属性,您的代码仍然可以工作。

您的表单还有一个保存 ViewModel 的属性:

private MyViewModel ViewModel => ...

您可以在构造函数中填写它,或者在每次需要时创建一个新的。您需要哪种方法取决于创建 ViewModel 的工作量。

定义显示哪些产品:

private BindingList<Product> DisplayedProducts
{
    get => (BindingList<Product>)this.dataGridViewProduct.DataSource;
    set => this.dataGridViewProduct.DataSource = value;
}

当然,您的表单需要一个过程来显示初始产品集:

private IEnumerable<Product> FetchInitialProductsToShow()
{
    return this.ViewModel.FetchOutOfStockProducts();
}

现在您要做的就是在加载表单时显示产品:

private void OnFormLoading(object sender, ...)
{
    this.DisplayedProducts = new BindingList<Product>(
        this.FetchInitialProductsToShow().ToList());
}

如果您在创建数据网格视图时允许,操作员可以添加/删除/更改产品。当他完成更改后,他可以通过单击“确定”或“立即应用”按钮通知您:

private void OnButtonOk_Clicked(object sender, ...)
{
    ICollection<Product> editedProducts = this.DisplayedProducts;
    // find out which Products are added / removed / changed
    this.ProcessEditedProducts(editedProducts);
}

顺便说一句,您是否注意到,因为我将模型与视图分开,所以您表单中的大多数过程都是“单行”?

两个不错的方法:获取当前产品,如果允许多选:获取所有选择的产品:

private Product CurrentProduct =>
    (Product) this.DataGridViewProducts.CurrentRow?.DataBoundItem;

private IEnumerable<Product> SelectedProducts =>
    this.DataGridViewProducts.SelectedRows
        .Cast<DataGridViewrow>()
        .Select(row => row.DataBoundItem)
        .Cast<Product>();

【讨论】:

  • 我不知道mvvm的概念。
【解决方案2】:

默认情况下,所有单元格都已可编辑。您必须单击两次以选择单元格,然后对其进行编辑或在选择单元格后按 F2。

您必须确保以下事项

  1. DataGridView 控件已启用。
  2. EditMode 属性值不是 EditProgrammatically。
  3. 单元格、行、列和控件的 ReadOnly 属性均设置为 false。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多