using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using ChatworkBulkSender.Utils;
namespace ChatworkBulkSender.UserControls
{
/// <summary>
/// マスタ画面DGVコントロールの基底クラス。
/// 検索・更新・ソートの機能を提供する。
/// </summary>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TDao"></typeparam>
/// <typeparam name="TForm"></typeparam>
[DesignerCategory("")] // デザイナーで表示しない
public abstract class AbstractBaseMasterDgvControl<TDto, TDao, TForm> : AbstractUserControl
where TDto : class
where TDao : class, new()
where TForm : Form
{
private IContainer components = null;
// Dgv
protected DataGridView _dgv = null;
// データリスト
protected List<TDto> _dataList = null;
// ソート可能なリスト
protected SortableBindingListUtil<TDto> _sortableList = null;
// 編集フォーム
protected TForm _individualEditForm = null;
// 検索条件
protected Dictionary<string, object> _searchCriteria = new Dictionary<string, object>();
// 編集ボタン列索引
protected abstract int EditButtonColumnIndex { get; }
// ソート可能な列数の最大索引
protected abstract int SortableColumnMaxIndex { get; }
// 初期ソートの列名
protected abstract string InitialSortColumnName { get; }
// 最終更新時刻
private DateTime? _lastLoadTime = null;
/// <summary>
/// 選択行の取得
/// </summary>
/// <returns></returns>
public TDto GetSelectedItem()
{
if (_dgv.CurrentRow != null)
{
return _dgv.CurrentRow.DataBoundItem as TDto;
}
// 選択行がない場合、nullを返す
return null;
}
/// <summary>
/// セルの選択をクリア
/// </summary>
public virtual void ClearSelection()
{
if (_dgv != null)
{
_dgv.ClearSelection();
_dgv.CurrentCell = null;
}
}
protected AbstractBaseMasterDgvControl()
{
// InitializeComponent();
// 派生クラスで呼び出し
}
/// <summary>
/// 継承先で実装。
/// 顧客データを取得する。
/// </summary>
/// <returns></returns>
protected abstract List<TDto> GetDataFromDao();
/// <summary>
/// 検索条件を取得し、検索を行う。
/// </summary>
/// <param name="criteria"></param>
public virtual void Search(Dictionary<string, object> criteria)
{
_searchCriteria = criteria ?? new Dictionary<string, object>();
// ソート可能なリストを再作成する
_sortableList = new SortableBindingListUtil<TDto>(GetDataFromDao());
_dgv.DataSource = _sortableList;
}
protected virtual void LoadData()
{
try
{
// データソースが設定されているか
if (_dgv.DataSource != null)
{
// 最新のデータリストを取得
_dataList = GetDataFromDao();
// 取得後、現在時刻に更新する
_lastLoadTime = DateTime.Now;
// ソート可能なリストを再作成する
_sortableList = new SortableBindingListUtil<TDto>(_dataList);
// 初期ソートを設定
if (!string.IsNullOrEmpty(InitialSortColumnName))
{
SetUpSortColumn(InitialSortColumnName);
}
_dgv.DataSource = _sortableList;
}
else
{
// 初回以降のロード時はソート状態を保持する
RefreshData();
}
}
catch(Exception ex)
{
MessageBoxUtil.ShowErr($"データの読み込み中にエラーが発生しました。\n\n{ex.Message}", "エラー");
}
}
/// <summary>
/// 最新のデータを取得した後、最終更新日時を現在時刻に設定する。
/// </summary>
protected virtual void RefreshData()
{
DataGridViewRefresherUtil.RefreshWithState<TDto>(
_dgv,
() => GetDataFromDao(),
(list) =>
{
_dataList = list;
_lastLoadTime = DateTime.Now;
_sortableList = new SortableBindingListUtil<TDto>(list);
return _sortableList;
}
);
}
protected virtual bool IsEditFormOpen()
{
return _individualEditForm != null &&
!_individualEditForm.IsDisposed &&
_individualEditForm.Visible;
}
protected abstract bool HasUpdateAfter(DateTime? lastLoadTime);
protected virtual void InitializeDgv()
{
if (_dgv == null) { return; }
// 列の自動生成を行わない
_dgv.AutoGenerateColumns = false;
// 行ヘッダ非表示
_dgv.RowHeadersVisible = false;
// ユーザーによる行の高さ変更を禁止
_dgv.AllowUserToResizeRows = false;
// 編集不可
_dgv.ReadOnly = true;
// 行単位で選択する形式とする
_dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
// 複数選択不可
_dgv.MultiSelect = false;
_dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
_dgv.CellClick += Dgv_CellClick;
_dgv.ColumnHeaderMouseDoubleClick += Dgv_ColumnHeaderMouseDoubleClick;
}
protected virtual void Dgv_CellClick(object sender, DataGridViewCellEventArgs e)
{
// ヘッダー行 または 編集セル列出ない場合はスキップ
if (e.RowIndex < 0 || e.ColumnIndex != EditButtonColumnIndex) { return; }
var selectedItem = _dgv.Rows[e.RowIndex].DataBoundItem as TDto;
if (selectedItem == null)
{
MessageBoxUtil.ShowErr("選択されたデータが取得できませんでした。","エラー");
return;
}
ShowEditForm(selectedItem);
}
/// <summary>
/// 編集フォームを表示する。
/// 継承先で実装。
/// </summary>
/// <param name="selectedItem"></param>
protected abstract void ShowEditForm(TDto selectedItem);
protected virtual void Dgv_ColumnHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.RowIndex == -1 && e.ColumnIndex >= 0 && e.ColumnIndex <= SortableColumnMaxIndex)
{
var propertyName = _dgv.Columns[e.ColumnIndex].DataPropertyName;
SetUpSortColumn(propertyName);
}
}
protected virtual void SetUpSortColumn(string propertyName)
{
if (!string.IsNullOrEmpty(propertyName))
{
var pd = TypeDescriptor.GetProperties(typeof(TDto))[propertyName];
if (pd != null && _sortableList != null)
{
_sortableList.ApplySort(pd);
}
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
components?.Dispose();
if (_individualEditForm != null && !_individualEditForm.IsDisposed)
{
_individualEditForm.Close();
_individualEditForm.Dispose();
}
}
base.Dispose(disposing);
}
}
}