for Push.
This commit is contained in:
@@ -0,0 +1,726 @@
|
||||
using KssSmaPlaLib.Commons;
|
||||
using KssSmaPlaLib.Forms.ContextMenuFunction;
|
||||
using KssSmaPlaLib.Ini;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace KssSmaPlaLib.Forms
|
||||
{
|
||||
public class DgvHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 汎用的な初期化
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void Initialize(DataGridView dgv)
|
||||
{
|
||||
// 行選択
|
||||
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
|
||||
// 行ヘッダ消去
|
||||
dgv.RowHeadersVisible = false;
|
||||
|
||||
// 編集不可
|
||||
dgv.ReadOnly = true;
|
||||
|
||||
// ユーザ操作制限
|
||||
dgv.AllowUserToAddRows = false;
|
||||
dgv.AllowUserToDeleteRows = false;
|
||||
dgv.AllowUserToOrderColumns = false;
|
||||
dgv.AllowUserToResizeColumns = true;
|
||||
dgv.AllowUserToResizeRows = false;
|
||||
|
||||
// 列ヘッダはセンタリング
|
||||
dgv.ColumnHeadersDefaultCellStyle.Alignment=DataGridViewContentAlignment.MiddleCenter;
|
||||
|
||||
//// ソート用余白を消す
|
||||
//dgv.ColumnHeadersDefaultCellStyle.Padding = new Padding(0);
|
||||
|
||||
// セル内余白(上下左右)をゼロに
|
||||
dgv.DefaultCellStyle.Padding = new Padding(0);
|
||||
|
||||
// 行高さの自動調整
|
||||
dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
|
||||
|
||||
// ダブルバッファ(プロパティが隠れている)
|
||||
var type = typeof(DataGridView);
|
||||
var prop = type.GetProperty("DoubleBuffered",
|
||||
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
|
||||
prop.SetValue(dgv, true, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列ヘッダのソート用余白を消す
|
||||
/// ※列が確定してからCallすること
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
//public static void ClearColumnHeaderSortYohaku(DataGridView dgv)
|
||||
//{
|
||||
// // 列ヘッダの幅にソート用の幅は不要
|
||||
// //foreach (DataGridViewColumn col in dgv.Columns) col.SortMode = DataGridViewColumnSortMode.NotSortable;
|
||||
|
||||
// // 何をやってもダメなので、テキストの先頭に余白入れます!👉ダメ!orz
|
||||
// //const string YOHAKU = " ";
|
||||
// //foreach (DataGridViewColumn col in dgv.Columns) col.HeaderText = YOHAKU + col.HeaderText;
|
||||
//}
|
||||
|
||||
// どちらのDTOでも使える共通バインド関数
|
||||
public static void BindListWithAttributeHeaders<T>(
|
||||
DataGridView grid,
|
||||
IList<T> source,
|
||||
bool isForce = false)
|
||||
{
|
||||
// 強制でないとき、データソースありなら何もしない
|
||||
if (!(grid.DataSource is null) && !isForce) return;
|
||||
|
||||
// データバインド完了後にヘッダー等を属性で上書き
|
||||
grid.DataBindingComplete += (_, __) => ApplyAttributeHeaders<T>(grid);
|
||||
|
||||
// 「とりあえず ToString() で文字列表示」したい場合の統一フォーマット
|
||||
grid.CellFormatting += (_, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// AutoGenerateColumnsだと各セルの Value はプロパティ値になります
|
||||
// ここで ToString() 統一(nullは空文字に)
|
||||
if (e.Value == null) { e.Value = string.Empty; e.FormattingApplied = true; return; }
|
||||
// 文化依存や日付/数値の既定書式を崩したくなければコメントアウト推奨
|
||||
if (!(e.Value is bool) &&
|
||||
string.IsNullOrEmpty(grid.Columns[e.ColumnIndex].DefaultCellStyle.Format))
|
||||
{
|
||||
e.Value = e.Value.ToString();
|
||||
e.FormattingApplied = true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
}
|
||||
};
|
||||
|
||||
grid.AutoGenerateColumns = true;
|
||||
|
||||
// 変更通知を効かせたい場合は BindingList に包む
|
||||
var bindingList = source is BindingList<T> bl ? bl : new BindingList<T>(source);
|
||||
|
||||
// BindingSource 経由が安定
|
||||
var bs = new BindingSource { DataSource = bindingList };
|
||||
grid.DataSource = bs;
|
||||
}
|
||||
|
||||
private const string KEY_NAME_DISPLAY_NAME_CSV = "DisplayNameCsv";
|
||||
|
||||
/// <summary>
|
||||
/// プライベートな子関数
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="grid"></param>
|
||||
public static void ApplyAttributeHeaders<T>(DataGridView grid)
|
||||
{
|
||||
// 編集した表示名
|
||||
var csv = IniHelper.ReadValue(null, grid.Parent.Name + "." + grid.Name, KEY_NAME_DISPLAY_NAME_CSV);
|
||||
|
||||
var props = TypeDescriptor.GetProperties(typeof(T))
|
||||
.Cast<PropertyDescriptor>()
|
||||
.ToDictionary(p => p.Name);
|
||||
|
||||
foreach (DataGridViewColumn col in grid.Columns)
|
||||
{
|
||||
var key = col.DataPropertyName ?? col.Name;
|
||||
if (key is null) continue;
|
||||
|
||||
if (props.TryGetValue(key, out var pd))
|
||||
{
|
||||
// タグに入れておく(PropertyDescriptor型)
|
||||
col.Tag = pd;
|
||||
|
||||
// 列ヘッダーを [DisplayName] に
|
||||
col.HeaderText = pd.DisplayName;
|
||||
|
||||
// 表示名を登録されてたら、置き換える
|
||||
var editName = StringUxer.GetStringByIndexFormCsv(csv,col.Index,string.Empty);
|
||||
if (!string.IsNullOrEmpty(editName)) col.HeaderText = editName;
|
||||
|
||||
// 文字寄せ
|
||||
var alignment =
|
||||
(col.HeaderText.IndexOf("[R]") >= 0 ? DataGridViewContentAlignment.MiddleRight :
|
||||
(col.HeaderText.IndexOf("[C]") >= 0 ? DataGridViewContentAlignment.MiddleCenter :
|
||||
DataGridViewContentAlignment.MiddleLeft));
|
||||
col.DefaultCellStyle.Alignment = alignment;
|
||||
col.HeaderText = col.HeaderText.Replace("[L]", "").Replace("[C]", "").Replace("[R]", "");
|
||||
|
||||
// [Browsable(false)] の列は非表示(AutoGenerateでも列が立つ場合の保険)
|
||||
var browsableAttr = pd.Attributes.OfType<BrowsableAttribute>().FirstOrDefault();
|
||||
if (browsableAttr != null && !browsableAttr.Browsable)
|
||||
{
|
||||
col.Visible = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 読み取り専用属性の尊重
|
||||
col.ReadOnly = pd.IsReadOnly;
|
||||
|
||||
// 便利系:ソートを自動に
|
||||
// col.SortMode = DataGridViewColumnSortMode.Automatic;
|
||||
|
||||
// 必要なら列幅の初期値
|
||||
// col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const string INI_KEY_COL_WIDTH_CSV = "ColWidthCsv";
|
||||
|
||||
/// <summary>
|
||||
/// 列幅保存(FormのFormClosingにてCall)
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvSaveColWidth(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = new List<int>();
|
||||
foreach(DataGridViewColumn col in dgv.Columns) list.Add(col.Width);
|
||||
IniHelper.WriteValue(null, section, INI_KEY_COL_WIDTH_CSV, string.Join(",", list));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列幅復元(FormのコンストラクタにてCall)
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvLoadColWidth(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = IniHelper.ReadValue(null, section,INI_KEY_COL_WIDTH_CSV).Split(',').ToList();
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (list.Count - 1 < col.Index) break;
|
||||
if (!int.TryParse(list[col.Index], out int val)) break;
|
||||
col.Width = val;
|
||||
}
|
||||
}
|
||||
|
||||
private const string INI_KEY_FONT_CSV = "Font";
|
||||
|
||||
public static void DgvSelectFont(Form form, DataGridView dgv)
|
||||
{
|
||||
if (!FontUxer.SelectFont(form, form.Name, dgv.Name + ".Font", dgv.DefaultCellStyle.Font, out var font)) return;
|
||||
DgvSetFontFromFont(dgv, font);
|
||||
DgvSaveFontToIni(dgv);
|
||||
}
|
||||
|
||||
|
||||
public static void DgvSetFontFromFont(DataGridView dgv, Font font)
|
||||
{
|
||||
var font2 = new Font(font.Name, font.Size, font.Bold ? FontStyle.Bold : FontStyle.Regular);
|
||||
dgv.DefaultCellStyle.Font = font2;
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font = font2;
|
||||
dgv.AutoResizeRows();
|
||||
}
|
||||
|
||||
public static void DgvSaveFontToIni(DataGridView dgv)
|
||||
{
|
||||
var fontCsv =
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font.Name + "," +
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font.Size.ToString() + "," +
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font.Bold.ToString();
|
||||
IniHelper.WriteValue(null, dgv.Parent.Name + "." + dgv.Name, INI_KEY_FONT_CSV, fontCsv);
|
||||
}
|
||||
|
||||
public static void DgvLoadFontFromIni(DataGridView dgv)
|
||||
{
|
||||
var defaultFontCsv =
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font.Name + "," +
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font.Size.ToString() + "," +
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font.Bold.ToString();
|
||||
var iniFontCsv = IniHelper.ReadValue(null, dgv.Parent.Name + "." + dgv.Name, INI_KEY_FONT_CSV, defaultFontCsv);
|
||||
var fontItems = iniFontCsv.Split(',');
|
||||
if (fontItems.Length != 3) fontItems = defaultFontCsv.Split(',');
|
||||
if (float.TryParse(fontItems[1], out var size) == false) size = dgv.ColumnHeadersDefaultCellStyle.Font.Size;
|
||||
if (bool.TryParse(fontItems[2], out var bold) == false) bold = dgv.ColumnHeadersDefaultCellStyle.Font.Bold;
|
||||
var font = new Font(fontItems[0], size, bold ? FontStyle.Bold : FontStyle.Regular);
|
||||
dgv.DefaultCellStyle.Font = font;
|
||||
dgv.ColumnHeadersDefaultCellStyle.Font = font;
|
||||
dgv.AutoResizeRows();
|
||||
}
|
||||
|
||||
private const string KEY_NAME_DISPLAY_INDEX_CSV = "DisplayIndexCsv";
|
||||
private const string KEY_NAME_COLUMN_VISIBLE_CSV = "ColumnVisibleCsv";
|
||||
|
||||
/// <summary>
|
||||
/// INIの列表示順をDGVに反映
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void SetColumnDisplayIndexFromIni(DataGridView dgv)
|
||||
{
|
||||
// 表示順(DisplayIndex)の設定
|
||||
var csv = IniHelper.ReadValue(null, dgv.Parent.Name + "." + dgv.Name, KEY_NAME_DISPLAY_INDEX_CSV);
|
||||
if (string.IsNullOrEmpty(csv)) return;
|
||||
var items = csv.Split(',');
|
||||
if (items.Length != dgv.Columns.Count) return;
|
||||
List<int> displayIndexList = new List<int>();
|
||||
foreach ( var item in items) displayIndexList.Add(int.Parse(item));
|
||||
for (var cnt = 0; cnt < dgv.Columns.Count; cnt++)
|
||||
{
|
||||
var index = displayIndexList.IndexOf(cnt);
|
||||
dgv.Columns[index].DisplayIndex = cnt;
|
||||
}
|
||||
|
||||
// 列の表示/非表示の設定
|
||||
csv = IniHelper.ReadValue(null, dgv.Parent.Name + "." + dgv.Name, KEY_NAME_COLUMN_VISIBLE_CSV);
|
||||
if (string.IsNullOrEmpty(csv)) return;
|
||||
items = csv.Split(',');
|
||||
if (items.Length != dgv.Columns.Count) return;
|
||||
List<bool> visibleList = new List<bool>();
|
||||
foreach (var item in items) visibleList.Add(bool.TryParse(item, out var boolValue) ? boolValue : true);
|
||||
for (var cnt = 0; cnt < dgv.Columns.Count; cnt++)
|
||||
{
|
||||
dgv.Columns[cnt].Visible = visibleList[cnt];
|
||||
}
|
||||
}
|
||||
|
||||
public static void MoveRow(DataGridView dgv, int rowIndex, bool moveUp)
|
||||
{
|
||||
// 移動先のインデックスを計算
|
||||
int targetIndex = moveUp ? rowIndex - 1 : rowIndex + 1;
|
||||
|
||||
// 範囲チェック(一番上より上、または一番下より下には行かない)
|
||||
if (targetIndex < 0 || targetIndex >= dgv.Rows.Count - (dgv.AllowUserToAddRows ? 1 : 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 選択状態などを保持したい場合の準備
|
||||
DataGridViewRow row = dgv.Rows[rowIndex];
|
||||
|
||||
// 一旦削除して挿入し直す
|
||||
dgv.Rows.RemoveAt(rowIndex);
|
||||
dgv.Rows.Insert(targetIndex, row);
|
||||
|
||||
// 移動後の行を選択状態にする(ユーザー体験向上)
|
||||
dgv.ClearSelection();
|
||||
dgv.Rows[targetIndex].Selected = true;
|
||||
dgv.CurrentCell = dgv.Rows[targetIndex].Cells[0];
|
||||
}
|
||||
|
||||
private const string INI_KEY_DGV_ROW_HEADER_HEIGHT = "DgvRowHeaderHeight";
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダ行の高さ保存
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvSaveHeaderHeight(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
IniHelper.WriteValue(null, section, INI_KEY_DGV_ROW_HEADER_HEIGHT, dgv.ColumnHeadersHeight.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダ行の高さロード
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvLoadHeaderHeight(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var str = IniHelper.ReadValue(null, section, INI_KEY_DGV_ROW_HEADER_HEIGHT, dgv.ColumnHeadersHeight.ToString());
|
||||
dgv.ColumnHeadersHeight = int.TryParse(str, out var intValue) ? intValue : dgv.ColumnHeadersHeight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 非表示列の再表示
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvRedispAllColumn(DataGridView dgv)
|
||||
{
|
||||
foreach (DataGridViewColumn col in dgv.Columns) col.Visible = true;
|
||||
}
|
||||
|
||||
private const string INI_KEY_COL_VISIBLE_CSV = "ColVisibleCsv";
|
||||
|
||||
/// <summary>
|
||||
/// 列の表示非表示を保存
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvSaveColVisible(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = new List<bool>();
|
||||
foreach (DataGridViewColumn col in dgv.Columns) list.Add(col.Visible);
|
||||
IniHelper.WriteValue(null, section, INI_KEY_COL_VISIBLE_CSV, string.Join(",", list));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列の表示非表示をロード
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvLoadColVisible(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = IniHelper.ReadValue(null, section, INI_KEY_COL_VISIBLE_CSV).Split(',').ToList();
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (list.Count - 1 < col.Index) break;
|
||||
if (!bool.TryParse(list[col.Index], out bool val)) break;
|
||||
col.Visible = val;
|
||||
}
|
||||
}
|
||||
|
||||
private const string INI_KEY_COL_DISPLAY_INDEX_CSV = "ColDisplayIndexCsv";
|
||||
|
||||
/// <summary>
|
||||
/// 列の表示順インデックスを保存
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvSaveColDisplayIndex(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = new List<string>();
|
||||
foreach (DataGridViewColumn col in dgv.Columns) list.Add($"{col.Name}={col.DisplayIndex}");
|
||||
IniHelper.WriteValue(null, section, INI_KEY_COL_DISPLAY_INDEX_CSV, string.Join(",", list));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列の表示順インデックスをロード
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvLoadColDisplayIndex(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = IniHelper.ReadValue(null, section, INI_KEY_COL_DISPLAY_INDEX_CSV).Split(',').ToList();
|
||||
if (list.Count == 1 && string.IsNullOrEmpty(list[0])) return;
|
||||
Dictionary<int,string> dic = new Dictionary<int,string>();
|
||||
foreach (var str in list)
|
||||
{
|
||||
dic.Add(int.Parse(str.Split('=')[1]), str.Split('=')[0]);
|
||||
}
|
||||
|
||||
// DisplayIndexは小さい方から設定しないと崩れる
|
||||
foreach (var di in dic.Keys.OrderBy(m => m))
|
||||
{
|
||||
dgv.Columns[dic[di]].DisplayIndex = di;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列幅の自動調整
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvColumnWidthAutoAdjust(DataGridView dgv)
|
||||
{
|
||||
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 行高さの自動調整
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvRowHeightAutoAdjust(DataGridView dgv)
|
||||
{
|
||||
dgv.AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列固定
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvColumnFix(DataGridView dgv)
|
||||
{
|
||||
if (dgv.CurrentCell == null) return;
|
||||
|
||||
// 1. 今クリックした列の「見た目の位置」を取得
|
||||
int targetDisplayIndex = dgv.CurrentCell.OwningColumn.DisplayIndex;
|
||||
|
||||
// 2. いったん全列の固定を解除(これをしないとエラーになる場合がある)
|
||||
DgvColumnFixKaijo(dgv);
|
||||
|
||||
// 3. 見た目の位置(DisplayIndex)が、ターゲット以下の列をすべて固定!
|
||||
// ※DisplayIndexの小さい順(左側から順)にFrozenをかけていくのがコツ
|
||||
var targetColumns = dgv.Columns.Cast<DataGridViewColumn>()
|
||||
.OrderBy(c => c.DisplayIndex);
|
||||
|
||||
foreach (var col in targetColumns)
|
||||
{
|
||||
if (col.DisplayIndex <= targetDisplayIndex)
|
||||
{
|
||||
col.Frozen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列固定解除
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvColumnFixKaijo(DataGridView dgv)
|
||||
{
|
||||
// 2. いったん全列の固定を解除(これをしないとエラーになる場合がある)
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
col.Frozen = false;
|
||||
}
|
||||
}
|
||||
|
||||
private const string INI_KEY_COL_FROZEN_CSV = "ColFrozenCsv";
|
||||
|
||||
/// <summary>
|
||||
/// 列の固定を保存
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvSaveColFrozen(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = new List<bool>();
|
||||
foreach (DataGridViewColumn col in dgv.Columns) list.Add(col.Frozen);
|
||||
IniHelper.WriteValue(null, section, INI_KEY_COL_FROZEN_CSV, string.Join(",", list));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 列の固定をロード
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvLoadColFrozen(DataGridView dgv)
|
||||
{
|
||||
var section = dgv.Parent.Name + "." + dgv.Name;
|
||||
var list = IniHelper.ReadValue(null, section, INI_KEY_COL_FROZEN_CSV).Split(',').ToList();
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (list.Count - 1 < col.Index) break;
|
||||
if (!bool.TryParse(list[col.Index], out bool val)) break;
|
||||
col.Frozen = val;
|
||||
}
|
||||
}
|
||||
|
||||
private const string INI_KEY_DGV_HEADER_BACK_COLOR = "DgvHeaderBackColor";
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダ背景色選択
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
/// <param name="dgv"></param>
|
||||
public static void DgvSelectHeaderBackColor(Form form, DataGridView dgv)
|
||||
{
|
||||
using (ColorDialog cd = new ColorDialog())
|
||||
{
|
||||
// 今の色を初期選択にしておく
|
||||
cd.Color = dgv.ColumnHeadersDefaultCellStyle.BackColor;
|
||||
|
||||
if (cd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
// 1. フォームの背景色を即時変更
|
||||
dgv.ColumnHeadersDefaultCellStyle.BackColor = cd.Color;
|
||||
|
||||
// 文字色を計算して算出し設定
|
||||
dgv.ColumnHeadersDefaultCellStyle.ForeColor = ColorHelper.GetContrastColor(dgv.ColumnHeadersDefaultCellStyle.BackColor);
|
||||
|
||||
// 2. 🔥 Colorを16進数(#RRGGBB)に変換してINIに書き込み
|
||||
string colorHex = ColorTranslator.ToHtml(cd.Color);
|
||||
IniHelper.WriteValue(null, form.Name, INI_KEY_DGV_HEADER_BACK_COLOR, colorHex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダ背景色(名前でマッチした列のみ)選択
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
/// <param name="dgv"></param>
|
||||
/// <param name="colNamePattern"></param>
|
||||
/// <param name="iniKey"></param>
|
||||
public static void DgvSelectHeaderBackColorWithNameMatch(Form form, DataGridView dgv, string colNamePattern, string iniKey)
|
||||
{
|
||||
// マッチする列を探し、現在の色を採取
|
||||
Color? color = null;
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (StringUxer.WildcardMatch(col.Name, colNamePattern))
|
||||
{
|
||||
color = col.HeaderCell.Style.BackColor;
|
||||
}
|
||||
}
|
||||
if (color == null)
|
||||
{
|
||||
MessageBox.Show(form, $"パターンにマッチする列なし[パターン:{colNamePattern}]");
|
||||
return;
|
||||
}
|
||||
|
||||
using (ColorDialog cd = new ColorDialog())
|
||||
{
|
||||
// 今の色を初期選択にしておく
|
||||
cd.Color = (Color)color;
|
||||
|
||||
if (cd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
var backColor = cd.Color;
|
||||
// 文字色を計算して算出し設定
|
||||
var foreColor = ColorHelper.GetContrastColor(backColor);
|
||||
|
||||
// DGVに反映
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (StringUxer.WildcardMatch(col.Name, colNamePattern))
|
||||
{
|
||||
col.HeaderCell.Style.BackColor = backColor;
|
||||
col.HeaderCell.Style.ForeColor = foreColor;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 🔥 Colorを16進数(#RRGGBB)に変換してINIに書き込み
|
||||
string colorHex = ColorTranslator.ToHtml(cd.Color);
|
||||
IniHelper.WriteValue(null, form.Name, iniKey, colorHex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダ背景色をINIから取得して設定
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
public static void DgvSetHeaderBackColorFromIni(Form form, DataGridView dgv)
|
||||
{
|
||||
var colorHex = IniHelper.ReadValue(null, form.Name, INI_KEY_DGV_HEADER_BACK_COLOR, ColorTranslator.ToHtml(dgv.ColumnHeadersDefaultCellStyle.BackColor));
|
||||
dgv.ColumnHeadersDefaultCellStyle.BackColor = ColorTranslator.FromHtml(colorHex);
|
||||
// 文字色を計算して算出し設定
|
||||
dgv.ColumnHeadersDefaultCellStyle.ForeColor = ColorHelper.GetContrastColor(dgv.ColumnHeadersDefaultCellStyle.BackColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダ背景色をINIから取得して設定(名前マッチング)
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
/// <param name="dgv"></param>
|
||||
/// <param name="colNamePattern"></param>
|
||||
/// <param name="iniKey"></param>
|
||||
public static void DgvSetHeaderBackColorFromIniWithNameMatch(Form form, DataGridView dgv, string colNamePattern, string iniKey)
|
||||
{
|
||||
// マッチする列を探し、現在の色を採取
|
||||
Color? color = null;
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (StringUxer.WildcardMatch(col.Name, colNamePattern))
|
||||
{
|
||||
color = col.HeaderCell.Style.BackColor;
|
||||
}
|
||||
}
|
||||
if (color == null)
|
||||
{
|
||||
MessageBox.Show(form, $"パターンにマッチする列なし[パターン:{colNamePattern}]");
|
||||
return;
|
||||
}
|
||||
|
||||
// INIから取得
|
||||
var colorHex = IniHelper.ReadValue(null, form.Name, iniKey, ColorTranslator.ToHtml((Color)color));
|
||||
var backColor = ColorTranslator.FromHtml(colorHex);
|
||||
var foreColor = ColorHelper.GetContrastColor(backColor);
|
||||
|
||||
// マッチする列に設定
|
||||
foreach (DataGridViewColumn col in dgv.Columns)
|
||||
{
|
||||
if (StringUxer.WildcardMatch(col.Name, colNamePattern))
|
||||
{
|
||||
col.HeaderCell.Style.BackColor = backColor;
|
||||
col.HeaderCell.Style.ForeColor = foreColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public const string TSV_PATH = @".\@@@DGV@@@.tsv";
|
||||
|
||||
/// <summary>
|
||||
/// DGVデータTSV保存
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
/// <param name="dgv"></param>
|
||||
public static void SaveGridDataToTsv(Form form, DataGridView dgv)
|
||||
{
|
||||
var path = TSV_PATH.Replace("@@@DGV@@@", $"{form.Name}.{dgv.Name}");
|
||||
try
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8))
|
||||
{
|
||||
foreach (DataGridViewRow row in dgv.Rows)
|
||||
{
|
||||
// 新規行(入力用の空行)はスキップ
|
||||
if (row.IsNewRow) continue;
|
||||
|
||||
// 各セルの値をタブで結合
|
||||
var cells = row.Cells.Cast<DataGridViewCell>().Select(c => c.Value?.ToString() ?? "");
|
||||
sw.WriteLine(string.Join("\t", cells));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("DGVのTSV保存に失敗しました: " + ex.Message);
|
||||
}
|
||||
}
|
||||
public static void LoadGridDataToTsv(Form form, DataGridView dgv)
|
||||
{
|
||||
var path = TSV_PATH.Replace("@@@DGV@@@", $"{form.Name}.{dgv.Name}");
|
||||
if (!File.Exists(path)) return;
|
||||
try
|
||||
{
|
||||
dgv.Rows.Clear();
|
||||
string[] lines = File.ReadAllLines(path, Encoding.UTF8);
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||
|
||||
// タブで分割して行を追加
|
||||
string[] values = line.Split('\t');
|
||||
dgv.Rows.Add(values);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("DGVのTSVによる復元に失敗しました: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SearchGrid(
|
||||
DataGridView dgv,
|
||||
string searchText,
|
||||
bool forward)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchText)) return;
|
||||
|
||||
int rowCount = dgv.RowCount;
|
||||
int colCount = dgv.ColumnCount;
|
||||
|
||||
// 現在のセルの位置を取得(選択されていなければ 0,0 から)
|
||||
int startRow = dgv.CurrentCell?.RowIndex ?? 0;
|
||||
int startCol = dgv.CurrentCell?.ColumnIndex ?? 0;
|
||||
|
||||
// 全セルをフラットなインデックスとして考えて計算
|
||||
int totalCells = rowCount * colCount;
|
||||
int startIndex = (startRow * colCount) + startCol;
|
||||
|
||||
for (int i = 1; i < totalCells; i++)
|
||||
{
|
||||
// forwardがtrueならプラス、falseならマイナス方向にずらす
|
||||
int offset = forward ? i : -i;
|
||||
int nextIndex = (startIndex + offset + totalCells) % totalCells;
|
||||
|
||||
int r = nextIndex / colCount;
|
||||
int c = nextIndex % colCount;
|
||||
|
||||
DataGridViewCell cell = dgv[c, r];
|
||||
|
||||
if (cell.Value != null && cell.Value.ToString().Contains(searchText))
|
||||
{
|
||||
dgv.CurrentCell = cell;
|
||||
return; // 見つかったら終了
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show("他には見つかりませんでしたにゃ!🐾");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user