首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

GridView 儲存格合併擴充方法:核心演算法完整實作

     編輯:關於C語言

演算法核心邏輯

合併原理:逐列掃描,比較當前列與後續列在指定欄位的值是否相同。相同則累計 RowSpan 計數並隱藏後續列儲存格;不同則中斷並移至下一組。

完整程式碼

public static class GridViewExtensions
{
    public static GridView RowSpan(this GridView gridView, object field)
    {
        var dict = ObjectToDictionary(field);
        int columnIndex = int.Parse(dict["ColumnIndex"]);
        string columnName = dict["ColumnName"];      // TemplateField 控制項 ID
        string propertyName = dict["PropertyName"];  // 取值屬性
        string columns = dict["Columns"];            // 同步合併欄位

        for (int i = 0; i < gridView.Rows.Count; i++)
        {
            int rowSpanCount = 1;
            for (int j = i + 1; j < gridView.Rows.Count; j++)
            {
                bool equal;
                if (string.IsNullOrEmpty(columnName))
                {
                    // 一般 BoundField
                    equal = gridView.Rows[i].Cells[columnIndex].Text ==
                            gridView.Rows[j].Cells[columnIndex].Text;
                }
                else
                {
                    // TemplateField:透過 FindControl 取得控制項再取屬性值
                    var ctrl1 = gridView.Rows[i].Cells[columnIndex].FindControl(columnName);
                    var ctrl2 = gridView.Rows[j].Cells[columnIndex].FindControl(columnName);
                    equal = GetPropertyValue(ctrl1, propertyName)?.ToString() ==
                            GetPropertyValue(ctrl2, propertyName)?.ToString();
                }

                if (equal)
                {
                    rowSpanCount++;
                    gridView.Rows[j].Cells[columnIndex].Visible = false;
                    if (!string.IsNullOrEmpty(columns))
                    {
                        columns.Split(',').ToList().ForEach(c =>
                            gridView.Rows[j].Cells[int.Parse(c)].Visible = false);
                    }
                }
                else break;
            }

            if (rowSpanCount > 1)
            {
                gridView.Rows[i].Cells[columnIndex].RowSpan = rowSpanCount;
                if (!string.IsNullOrEmpty(columns))
                {
                    columns.Split(',').ToList().ForEach(c =>
                        gridView.Rows[i].Cells[int.Parse(c)].RowSpan = rowSpanCount);
                }
                i += rowSpanCount - 1; // 跳過已合併的列
            }
        }
        return gridView;
    }

    private static Dictionary<string, string> ObjectToDictionary(object obj)
    {
        var result = new Dictionary<string, string>();
        var props = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
        foreach (var p in props)
            result.Add(p.Name, p.GetValue(obj)?.ToString());

        // 預設值
        if (!result.ContainsKey("ColumnIndex")) throw new Exception("未指定 ColumnIndex");
        if (!result.ContainsKey("ColumnName")) result.Add("ColumnName", null);
        if (!result.ContainsKey("PropertyName")) result.Add("PropertyName", "Text");
        if (!result.ContainsKey("Columns")) result.Add("Columns", null);
        return result;
    }

    private static object GetPropertyValue(object obj, string propName)
    {
        if (obj == null) return null;
        var pi = obj.GetType().GetProperty(propName);
        return pi?.GetValue(obj);
    }
}

關鍵細節解析

  1. 雙重迴圈 + 跳列優化:外層 i 走訪每列,內層 j 向下比對;合併完成後 i += rowSpanCount - 1 直接跳過已處理列。
  2. 統一處理 BoundField / TemplateField:透過 columnName 是否為空判斷模式,TemplateField 使用 FindControl + 反射取值。
  3. 同步合併欄位:Columns 字串分割後,對每個索引同步設定 Visible = false 與 RowSpan。
  4. 匿名型別轉 Dictionary:利用反射列舉屬性,彈性擴充參數,並提供預設值與驗證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved