【问题标题】:How to change the value of a cell in a gridview at runtime?如何在运行时更改网格视图中单元格的值?
【发布时间】:2013-12-08 16:24:01
【问题描述】:

详情

我有一个datagridview 来处理来自数据库的数据。我有一列有数值,每个数字代表一个字符串值,例如,

0 => "group 1", 
1 => "group 2" 
and so on...

用户必须将此数据视为可读格式,即 0 => “组 1”。像这样:

id          priceGroupID
----------- ------------
1234        -1 => "group -1"
36968       0  => "group  0"
1           2  => "group  2"
2           2  => "group  2"
3           2  => "group  2"
1003        2  => "group  2"

在这个链接中:(stackoverflow.com/questions/10314996/…) 代表一个想法,但我想要别的东西。更强大的东西。不要害羞,如果没有其他方法,请告诉我没有。

总结和问题

简而言之:

  • 我想在 Gridview 中显示这些数据,而不对我的数据库进行任何更改。
  • 我想要建议的格式。有没有一种简单的方法来制作这种格式,意思是n => "group m"
  • cellformatting 不是我想要的。 CellFormatting 只是根据数据格式格式化单元格。 (msdn)

还有一件事:我的编程语言是 windows 应用程序中的 c#。

我希望说出我的意思。

提前致谢。

【问题讨论】:

  • 我在某处读到了有关 cellFormatting 的信息,但这不是一个好主意并且会降低程序的速度。最终我认为我必须使用它。
  • cellformatting 不是您在这里想要的……至少,从问题和示例来看。 cellformatting 只是根据数据格式msdn.microsoft.com/en-us/library/… 格式化单元格
  • 这种方法的坏处是当用户编辑单元格“Group 7”不合法并且它不解析格式时,用户必须将“Group 4”更改为“4”或你必须在其他活动中为他们做这件事。

标签: c# sql .net gridview


【解决方案1】:

让我们看看你得到了什么。

我想在 gridview 中显示这些数据而不更改我的数据库。

太好了,应该是这样的。 数据必须与数据表示分开。

cellformatting 不是我想要的。 cellformatting 只是根据数据格式格式化单元格。

错了!

格式化正是您所需要的。一个相同的数据可以用多种方式表示。例如,一个和数字或日期值可以使用数千种方式(格式)显示(格式化)。这正是string.Format(和其他Format)方法所做的。另一个例子是Checkbox 显示bool 值。另一个例子是ComboBoxValueMember 显示为DisplayMember。等等。

事实上,您的要求是Format 函数的变体,可以通过Custom Numeric Format String 来实现。您只需将DataGridViewColumn.DefaultCellStyle 属性Format 设置为“Group 0”。

如果格式不够,与某些人所说的相反,CellFormatting 事件正是您所需要的。

默认情况下,DataGridView 控件会尝试将单元格的值转换为适合显示的格式。例如,它将数值转换为字符串,以便在文本框单元格中显示。您可以通过设置由 DefaultCellStyle 属性等属性返回的 DataGridViewCellStyle 的 Format 属性来指示要使用的格式设置。

如果标准格式不足,可以通过处理CellFormatting事件自定义格式。此事件允许您指示要用于单元格显示的确切显示值以及单元格样式,例如背景和前景色。这意味着您可以针对任何类型的单元格格式处理此事件,而不管单元格值本身是否需要格式化。

大部分时候对性能的影响可以忽略不计,因为只有在需要在屏幕上显示时才将值转换为字符串,并且屏幕的行数与总行数相比是有限的(以防万一你有一个庞大的数据)。

值/显示文本分离的优点之一是网格排序工作正常(按数字而不是按文本)。

总之,不要上当转换您的数据存储值以供显示。每个控件都有格式化功能,只需使用它们。由于您要求一种简单的方法,Format 属性是您的情况下最简单但有效的解决方案。

这是一个包含 100,000 行的示例,其中使用了两种格式设置方法(注释一个,取消注释另一个)。可以看到绝对没有性能问题,GroupId 列排序工作正常。

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        static void UseFormat(DataGridView dg)
        {
            dg.ColumnAdded += (sender, e) =>
            {
                if (e.Column.DataPropertyName == "GroupId")
                {
                    e.Column.DefaultCellStyle.Format = "Group 0";
                }
            };
        }

        static void UseCellFormatting(DataGridView dg)
        {
            dg.CellFormatting += (sender, e) =>
            {
                if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
                {
                    var column = dg.Columns[e.ColumnIndex];
                    if (column.DataPropertyName == "GroupId" && e.Value != null)
                    {
                        e.Value = "Group " + e.Value.ToString();
                        e.FormattingApplied = true;
                    }
                }
            };
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var dg = new DataGridView { Dock = DockStyle.Fill, Parent = form, ReadOnly = true, AllowUserToAddRows = false };
            UseFormat(dg);
            //UseCellFormatting(dg);
            var data = new DataTable();
            data.Columns.Add("Id", typeof(int));
            data.Columns.Add("GroupId", typeof(int));
            var groupIds = Enumerable.Range(0, 15).ToArray();
            for (int i = 0; i < 100000; i++)
                data.Rows.Add(i, groupIds[i % groupIds.Length]);
            dg.DataSource = data;
            Application.Run(form);
        }
    }
}

【讨论】:

    【解决方案2】:

    当然,很简单。

    您需要访问后跟列名的行索引并设置其值。例如:

    this.dataGridView.Rows[0].Cells["FirstName"].Value = "billy";
    

    此示例访问第一行和单元格“FirstName”并将其值更改为“billy”。

    更改不会影响数据库,但可能会影响数据源绑定,从而导致数据源发生更改。相反,您可能不希望引用数据源,因此当您对数据源进行操作(例如更新)时,更改不会最终提交回数据库。

    【讨论】:

    • 谢谢你,但你认为我们有 10000 行。在这种情况下,您不能一一更改所有这些。
    • 好吧,您还要如何更新有问题的单元格?您也没有声明您将拥有 10000 行或更多行,因此要求并不完全清楚。此外,显示行数在内存消耗和性能方面都是一个大问题。最佳做法是限制返回的记录数量(如分页系统)。
    • 哦,对不起,我没有清楚地解释我的问题。在这个链接中:(stackoverflow.com/questions/10314996/…) 代表一个想法,但我想要别的东西。在这种情况下你能帮我吗?同时,您在类似 page ystem 中显示行的建议是一个不错的建议,但您是否想过“如何实现这一点?”。
    • 在您的数据库中,您需要进行分页。传入当前页面和每页的项目。解释起来有点冗长,但一个简单的谷歌可以帮助你了解如何做到这一点。转到您的原始问题和链接,问题在于您将有数千个 if/else 语句来执行您的要求...
    • 亲爱的@Ahmedilyas,​​感谢您的帮助。 Telerik 代表了一个支持分页的新组件。它对我有很大帮助。
    【解决方案3】:

    试试这个,你必须创建一个 foreach 循环来遍历 datagridview 中的所有项目,这个例子显示你只为第一条记录更改它:

    int groupIdentifier = this.dataGridView.Rows[0].Cells["Group"].Value;
    
    this.dataGridView.Rows[0].Cells["Group"].Value = GetGroupName(groupIdentifier);
    
    List<Groups> ListGroups = new List<Groups>();
    
    private string GetGroupName(int groupIdentifier)
    {
        var group = ListGroups.FirstOrDefault(g=>g.Id == groupIdentifier);
        return group.Name;
    }
    

    在填充网格时使用它。

    希望对你有帮助

    【讨论】:

    • 亲爱的@RaZor,谢谢你,但这不是我想要的。但这对我有很大帮助。你能推荐我你提到的朋友吗:c# chatroom
    • mostafa,np,我是来帮助并尝试回答问题的 :) 我在 c# 聊天中没有提到朋友,但如果我遇到对数据网格有更多经验的人,我'我会让你知道,我会让他看看这个问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    相关资源
    最近更新 更多