在Winform分頁控制元件中整合儲存使用者列表顯示欄位及寬度調整設定

2023-05-06 12:00:30

在Winform的分頁控制元件裡面,我們提供了很多豐富的功能,如常規分頁,中文跳脫、匯出Excel、匯出PDF等,基於DevExpress的樣式的分頁控制元件,我們在其上面做了不少封裝,以便更好的使用,其中就包括整合儲存使用者列表顯示欄位及寬度調整設定。本篇隨筆介紹這個實現的過程,通過在當前程式中序列化方式儲存一個記錄使用者設定的檔案,提供媒介的儲存和載入處理。

1、整合儲存使用者列表顯示欄位及寬度調整設定的需求

在一些使用者列表使用的反饋中,希望能夠在調整列表欄位和它的順序,以及能夠儲存上次調整記錄的寬度,因此,涉及到欄位可見列表、欄位順序,列寬度的內容儲存,這些功能應該是對使用者透明的,不需要開發人員干預,也不需要使用者過多操作就能實現的,也就是在使用者調整的時候,自動記錄這些資訊,並儲存起來,下一次開啟頁面的時候,自動載入上次的設定資訊即可,邏輯也算比較簡單。

因此我們需要檢測使用者對列寬度調整的事件,記錄列欄位寬度的資訊,如果使用者調整欄位顯示和順序,那麼控制元件也需要對它進行記錄起來,供下次載入使用。

對於DevExpress的列寬調整,有一個事件,我們在控制元件邏輯中實現它,記錄它的變化並儲存即可

 this.gridView1.ColumnWidthChanged += GridView1_ColumnWidthChanged;

然後我們在事件的實現中,判斷使用者是否啟用自定義設定處理,然後進行儲存列寬處理即可。

        private void GridView1_ColumnWidthChanged(object sender, DevExpress.XtraGrid.Views.Base.ColumnEventArgs e)
        {
            //如果不設定,預設不處理
            if (!this.EnableColumnsSetting) return;

            GridViewHelper.SaveColumnSetting(this.gridView1, this.ParentForm?.Name);
        }

為了方便,我們把一些邏輯分離到一個獨立的輔助檔案上,實現程式碼如下所示。

/// <summary>
/// 儲存列設定
/// </summary>
/// <param name="settings">當前設定資訊</param>
/// <param name="gridViewName">檢視名稱</param>
/// <param name="parentFormName">父類別表單名稱,用於區分</param>
public static void SaveColumnSetting(GridColumnSetting settings, string gridViewName,  string parentFormName)
{
    if (settings != null)
    {
        var folderPath = $"{Environment.CurrentDirectory}/ColumnSetting";
        var filePath = $"{folderPath}/{parentFormName}.{gridViewName}.setting";

        // 檢查資料夾是否存在
        if (!Directory.Exists(folderPath))
        {
            Directory.CreateDirectory(folderPath);
        }
        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, settings);
        }
    }
}

上面主要就是對設定資訊進行序列化到一個檔案中進行中轉,從而避免資料庫的處理,同時又會因為不同使用者記錄不同的設定資訊。對於不同的頁面,我們通過表單名稱來區分不同的設定,因為分頁控制元件場景需要一個唯一的標識來區分不同的資料場景。

而對於可見欄位,以及它的順序調整,那麼我們為了方便,提供一個設定的介面給終端使用者使用即可,通過列表右鍵選單觸發入口,如下介面所示。

 在列表框中列出介面的所有列(包括隱藏列),並通過拖動或者按鈕調整順序,通過勾選設定可見性,如下介面所示。

 上面的列表控制元件,是一個標準的CheckedListBox控制元件,通過處理它的拖動事件,實現可拖動順序的調整。

    // 繫結 ListBoxControl 控制元件的事件,實現拖拉處理
    listBoxControl.DragDrop += ListBoxControl_DragDrop;
    listBoxControl.DragOver += ListBoxControl_DragOver;
    listBoxControl.MouseDown += ListBoxControl_MouseDown;

而讀取上面的列表中的可見列欄位及順序,我們通過組態檔中進行讀取,並反序列化即可。

/// <summary>
/// 獲取設定資訊
/// </summary>
/// <param name="gridView">當前檢視</param>
/// <param name="parentFormName">父類別表單名稱,用於區分</param>
/// <returns></returns>
public static GridColumnSetting GetSettings(GridView gridView, string parentFormName)
{
    var folderPath = $"{Environment.CurrentDirectory}/ColumnSetting";
    var filePath = $"{folderPath}/{parentFormName}.{gridView.Name}.setting";
    if (!File.Exists(filePath)) return null;

    //反序列化 
    GridColumnSetting settings = null;
    using (FileStream stream = new FileStream(filePath, FileMode.Open))
    {
        var formatter = new BinaryFormatter();
        settings = (GridColumnSetting)formatter.Deserialize(stream);
    }
    return settings;
}

對於使用者調整後的設定儲存,記錄好相關資訊後進行序列化到檔案中即可,如下實現邏輯所示。

private void btnOK_Click(object sender, EventArgs e)
{
    //記錄所有的列寬
    var sb = new StringBuilder();
    var visibleSb = new StringBuilder();
    int index = 0;
    foreach (var objItem in this.listBoxControl.Items)
    {
        var item = objItem as CListItem;
        if (item != null)
        {
            var checkState = this.listBoxControl.GetItemChecked(index);
            if (checkState)
            {
                var column = this.GridView.Columns.ColumnByFieldName(item.Value);
                if (column != null)
                {
                    sb.Append($"{item.Value}:{column.Width},");
                    visibleSb.Append($"{item.Value},");
                }
            }
        }
        index++;
    }

    var columnsWidth = sb.ToString().Trim(',');
    var columnsVisbile = visibleSb.ToString().Trim(',');
    var settings = new GridColumnSetting(columnsWidth, columnsVisbile);

    //如果不設定,預設不處理
    GridViewHelper.SaveColumnSetting(settings, this.GridView.Name, this.Owner?.Name);
}

最終,我們在開發具體頁面資料展示的時候,把分頁控制元件拖動到介面上就可以了,預設具有這些效果,不需要另外增加實現程式碼,從而通過封裝的方式,簡化了很多基礎的功能處理,並能夠給使用者一致的體驗和介面效果。