5

有没有办法在datagridview没有数据绑定的情况下添加列页脚?我正在使用它来获取用户输入以添加库存。目前我正在使用标签来显示总数,但如果可能的话,我想将其更改为页脚。

4

3 回答 3

7

我之前遇到过同样的问题,经过长时间的搜索后我意识到;

  1. Winform Datagridview 不支持添加页脚。

  2. 我尝试添加一个可以保存摘要的额外行,但仍然无法正常工作。

  3. 您可以创建一个用户控件,该控件具有两个网格并且下方的网格包含摘要。

解决方案 - 在此处输入图像描述

  1. 我使用数据绑定的解决方案。(1)-我创建一个具有(名称、成本)属性的抽象对象项目。(2)-我创建一个具体项目,即继承项目的ConcItem (3)-我创建一个页脚项目,即FooterItem这也继承了Item (4) - Items 的集合,即 ItemList,您在其中实例化页脚项。(5) 最后,在您进行数据绑定之前,调用添加页脚项的方法。

    public abstract class Item
    {
      public virtual string Name { get; set; }
      public virtual int Cost { get; set; }
    }
    public  class ConcItem:Item
    {
      public override string Name { get; set; }
      public override int Cost { get; set; }        
    }
    public  class FooterItem:Item 
    {
      public override string Name { get { return "Total"; } }
      public override int Cost { get; set; }
    }
    public class ItemList : List<Item>
    {
      private Item _footer;
    
      public void SetFooter()
      {
        _footer = new FooterItem();            
        foreach (var item in this)
        {
          _footer.Cost += item.Cost;              
        }
        this.Add(_footer);
      }
    }
    
    
    public partial class Form1 : Form
    {
      Item _item;
      ItemList _itemList;
      public Form1()
      {
        InitializeComponent();
        dgv.DataBindingComplete += dgv_DataBindingComplete;
        _itemList = new ItemList();
    
        SetSampleData();
      }
      private void SetSampleData()
      {
        _item = new ConcItem();
        _item.Name = "Book";
        _item.Cost = 250;
        _itemList.Add(_item);
    
        _item = new ConcItem();
        _item.Name = "Table";
        _item.Cost = 500;
        _itemList.Add(_item);
    
        _item = new ConcItem();
        _item.Name = "PC";
        _item.Cost = 700;
        _itemList.Add(_item);
    
        dgv.DataSource = null;
        _itemList.SetFooter();  //Add the footer item b4  data binding
        dgv.DataSource = _itemList;
      }
      void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
      {
        //If you want to do some formating on the footer row
        int rowIndex = dgv.Rows.GetLastRow(DataGridViewElementStates.Visible);
        if (rowIndex <= 0)
        {
          return;
        }
        dgv.Rows[rowIndex].DefaultCellStyle.BackColor = Color.Red;
        dgv.Rows[rowIndex].DefaultCellStyle.SelectionBackColor = Color.Red;        
        dgv.Rows[rowIndex].DefaultCellStyle.Font = new Font("Microsoft Sans Serif", 12f,    FontStyle.Bold);
      }
    }
    
于 2012-10-25T13:00:47.237 回答
2

在我的一个应用程序中,我通过像这样利用 DataGridView 的 NewRow 来解决它。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.dataGridView1.CellFormatting += dataGridView1_CellFormatting;
            this.dataGridView1.CellValueChanged += dataGridView1_CellValueChanged;
        }

        void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex != this.dataGridView1.NewRowIndex && e.ColumnIndex == 2)
            {
                this.dataGridView1.InvalidateRow(this.dataGridView1.NewRowIndex);
            }
        }

        void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (e.RowIndex == this.dataGridView1.NewRowIndex)
            {
                e.CellStyle.Font = new Font(e.CellStyle.Font, FontStyle.Bold);
                e.CellStyle.ForeColor = Color.Red;
                switch (e.ColumnIndex)
                {
                    case 0:
                        e.Value = "Total";
                        break;

                    case 2:
                        var sum = 0.0d;
                        for (int i = 0; i < this.dataGridView1.NewRowIndex; i++)
                        {
                            var value = this.dataGridView1[2, i].Value;
                            if (value is double)
                            {
                                sum += ((double)value);
                            }
                        }
                        e.Value = Math.Round(sum, 2);
                        break;
                    // Single line version of case 2 would be
                    // e.Value = this.dataGridView1.Rows.Cast<DataGridViewRow>().Where(a => a.Index != a.DataGridView.NewRowIndex).Select(a => (double)a.Cells[2].Value).Sum().ToString("N2");
                }
            }
        }

    }
}

这是它如何工作的实时屏幕截图。

在此处输入图像描述

于 2017-07-23T18:53:45.987 回答
0

有一个更好的解决方案。在这个解决方案中,每次单元格内容发生变化时,都会重新计算并显示该值。

我的数据网格视图如下所示。

数据网格

在此解决方案中,您可以拥有任意数量的列和任意数量的行。

private void updateDataGridViewTotal(DataGridView dgv)
    {
        DataTable dt = (DataTable)dgv.DataSource;
        int lastRow = (dgv.Rows.Count - 1);
        if (dt.Rows[lastRow][0].ToString() == "Total")
        {
            dt.Rows.RemoveAt(lastRow);
        }
        int[] tot = new int[dt.Columns.Count];
        Array.Clear(tot, 0, tot.Length);

        foreach (DataRow row in dt.Rows)
        {
            int rowSum = 0;
            for (int i = 1; i < dt.Columns.Count - 1; i++)
            {
                tot[i] += Convert.ToInt32(row[i]);
                rowSum += Convert.ToInt32(row[i]);
            }
            row["Total"] = rowSum;
        }
        DataRow newRow = dt.NewRow();
        newRow["Agent"] = "Total";
        for (int i = 1; i < tot.Length; i++)
        {
            newRow[i] = tot[i];
        }
        dt.Rows.Add(newRow);
        dgv.DataSource = dt;
    }

只需将您的 datagridview 传递给该函数。

于 2020-09-01T03:20:50.140 回答