DepartmentProject/DepartmentPortal/Common/DesktopTools/MainControls/GenericControlEntityList.cs

584 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DesktopTools.Enums;
using DesktopTools.Helpers;
using DesktopTools.Interfaces;
using DesktopTools.Models;
using ModuleTools.Attributes;
using ModuleTools.BindingModels;
using ModuleTools.BusinessLogics;
using ModuleTools.Enums;
using ModuleTools.Extensions;
using ModuleTools.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
namespace DesktopTools.Controls
{
public partial class GenericControlEntityList<G, S, L, E, BL> : MainControlViewEntityList, IControlViewEntityList
where G : GetBindingModel, new()
where S : SetBindingModel, new()
where L : ListViewModel<E>
where E : ElementViewModel
where BL : GenericBusinessLogic<G, S, L, E>
{
/// <summary>
/// Режим работы
/// </summary>
private ControlOpenMode _openMode;
/// <summary>
/// Событие, вызываемое при закрытии контрола
/// </summary>
private event Action<Guid> CloseListEvent;
/// <summary>
/// Событие, вызываемое при закрытии контрола
/// </summary>
private event Action<bool> CloseSelectEvent;
/// <summary>
/// Объект бизнес-логики для получения данных
/// </summary>
protected BL _businessLogic;
/// <summary>
/// Методы для реализации в generic-контроле
/// </summary>
protected IGenericControlEntityList<L, E> _genericControlViewEntityList;
/// <summary>
/// Список значений с контролов с панели поиска
/// </summary>
protected List<(string Name, object Value)> _searchValues;
/// <summary>
/// Констркутор
/// </summary>
public GenericControlEntityList()
{
InitializeComponent();
InitEvents();
_businessLogic = DependencyManager.Instance.Resolve<BL>();
_controlViewEntityList = this;
}
#region IControlViewEntityList
public async void OpenControl(ControlOpenModel model)
{
_openMode = model.OpenMode;
if (model.CloseList != null)
{
CloseListEvent += model.CloseList;
}
if (model.CloseSelect != null)
{
CloseSelectEvent += model.CloseSelect;
}
if (dataGridViewList.Columns.Count == 0)
{
try
{
Configurate(GetConfig());
}
catch (Exception ex)
{
DialogHelper.MessageException(ex.Message, "Ошибка при конфигурации");
}
}
await LoadListAsync();
}
public IControl GetInstanceControl() => _genericControlViewEntityList?.GetInstanceGenericControl();
public string GetTitleFromIdControl(Guid id) => _businessLogic.GetElement(new G { Id = id })?.ToString();
public string SaveControlToXml() => new XElement("Control",
new XAttribute("Type", GetType().FullName),
new XAttribute("ControlId", ControlId),
new XAttribute("Title", Title),
new XAttribute("AccessOperation", AccessOperation),
new XElement("Configurate",
new XElement("Page", toolStripTextBoxPage.Text),
new XElement("CountElementsOnPage", toolStripTextBoxCountRecords.Text),
new XElement("PageName",
new XElement("Key", ((toolStripComboBoxPageNames.SelectedItem as PageNamesForPaginationModel)?.Key ?? "-")),
new XElement("Value", ((toolStripComboBoxPageNames.SelectedItem as PageNamesForPaginationModel)?.Value ?? "-"))),
new XElement("ParentId", ParentId?.ToString() ?? "-"))).ToString();
public void LoadControlFromXml(string xml)
{
var control = XElement.Parse(xml).Element("Control");
ControlId = new Guid(control.Attribute("ControlId").Value.ToString());
Title = control.Attribute("Title").Value.ToString();
AccessOperation = (AccessOperation)Enum.Parse(typeof(AccessOperation), control.Attribute("AccessOperation").Value.ToString());
var config = control.Element("Configurate");
toolStripTextBoxPage.Text = config.Element("Page").Value.ToString();
toolStripTextBoxCountRecords.Text = config.Element("CountElementsOnPage").Value.ToString();
if (config.Element("PageName").Element("Key").Value.ToString() != "-")
{
var pageName = new PageNamesForPaginationModel
{
Key = config.Element("PageName").Element("Key").Value.ToString(),
Value = config.Element("PageName").Element("Value").Value.ToString()
};
toolStripComboBoxPageNames.SelectedItem = pageName;
}
if (config.Element("ParentId").Value.ToString() != "-")
{
ParentId = new Guid(config.Element("ParentId").Value.ToString());
}
}
#endregion
/// <summary>
/// Конфигуратор контрола
/// </summary>
/// <param name="model">Настройки</param>
private void Configurate(ControlViewEntityListConfiguration config)
{
if (config == null)
{
return;
}
// формирование таблицы на основе модели
dataGridViewList.Columns.Clear();
var properties = typeof(E).GetProperties();
foreach (var property in properties)
{
var attr = property.GetCustomAttribute<ViewModelControlListPropertyAttribute>();
if (attr != null)
{
var colIndex = attr.DisplayName == "Идентификатор" ? 0 : dataGridViewList.Columns.Count;
dataGridViewList.Columns.Insert(colIndex, new DataGridViewTextBoxColumn
{
HeaderText = attr.DisplayName,
Name = string.Format("Column{0}", property.Name),
ReadOnly = true,
Visible = !attr.IsHide,
Width = attr.ColumnWidth ?? 0,
AutoSizeMode = attr.ColumnWidth.HasValue ? DataGridViewAutoSizeColumnMode.None : DataGridViewAutoSizeColumnMode.Fill
});
}
}
labelTitle.Text = Title;
// настройка отображения основных кнопок
if (config.HideToolStripButton != null)
{
foreach (var elem in config.HideToolStripButton)
{
var ctrl = toolStripMenu.Items.Find(elem.ToString(), false);
if (ctrl != null && ctrl.Length > 0)
{
ctrl[0].Visible = false;
switch (elem)
{
case ToolStripButtonListNames.toolStripButtonAdd:
toolStripSeparator1.Visible = false;
break;
case ToolStripButtonListNames.toolStripButtonUpd:
toolStripSeparator2.Visible = false;
break;
case ToolStripButtonListNames.toolStripButtonDel:
toolStripSeparator3.Visible = false;
break;
case ToolStripButtonListNames.toolStripButtonSearch:
toolStripSeparator4.Visible = false;
break;
case ToolStripButtonListNames.toolStripButtonRef:
toolStripSeparator5.Visible = false;
break;
}
}
}
}
// Загрузка подпунктов в контекстное меню и в пункт меню "Действие"
if (config.ControlOnMoveElem != null)
{
foreach (var elem in config.ControlOnMoveElem)
{
ToolStripMenuItem item = new() { Text = elem.Value.Title, Name = elem.Key };
item.Click += elem.Value.Event;
toolStripSplitButtonActions.DropDownItems.Add(item);
contextMenuStripDataGrid.Items.Add(item);
}
}
// либо скрытие пункта, если не предусмотренно подпунктов
else
{
toolStripSplitButtonActions.Visible = false;
toolStripSeparator5.Visible = false;
}
toolStripFooter.Visible = config.PaginationOn;
// Пагинация
if (config.PaginationOn)
{
// пагинация по страницам
if (config.CountElementsOnPage.HasValue)
{
toolStripTextBoxCountRecords.Text = config.CountElementsOnPage.Value.ToString();
toolStripLabelPageName.Visible = toolStripComboBoxPageNames.Visible = false;
}
// пагинация по названиям
else if (config.PageNamesForPagination != null)
{
toolStripButtonPrev.Visible = toolStripLabelPage.Visible = toolStripTextBoxPage.Visible = toolStripLabelCountPages.Visible =
toolStripLabelCountRecords.Visible = toolStripTextBoxCountRecords.Visible = toolStripButtonNext.Visible = false;
toolStripComboBoxPageNames.Items.AddRange(config.PageNamesForPagination.ToArray());
toolStripComboBoxPageNames.SelectedIndex = 0;
toolStripComboBoxPageNames.Tag = config.ParentPropertyName;
}
}
// при вызове контрола для выбора элемента, делаем возможность выбора только одной записи
dataGridViewList.MultiSelect = _openMode == ControlOpenMode.List;
// Открытие через родительский элемент
if (_openMode == ControlOpenMode.Child)
{
panelHeader.Visible = false;
toolStripButtonClose.Visible = false;
toolStripFooter.Visible = false;
toolStripSeparator6.Visible = true;
toolStripButtonSelect.Visible = true;
}
Dock = DockStyle.Fill;
}
/// <summary>
/// Инициализация событий к контролам
/// </summary>
private void InitEvents()
{
toolStripButtonAdd.Click += (object sender, EventArgs e) => { AddElement(); };
toolStripButtonUpd.Click += (object sender, EventArgs e) => { UpdElement(); };
toolStripButtonDel.Click += (object sender, EventArgs e) => { DelElement(); };
toolStripButtonSearch.Click += (object sender, EventArgs e) => { panelSearch.Visible = !panelSearch.Visible; _searchValues?.Clear(); };
toolStripButtonRef.Click += async (object sender, EventArgs e) => { await LoadListAsync(); };
toolStripButtonSelect.Click += (object sender, EventArgs e) => { SelectElement(); };
toolStripButtonClose.Click += (object sender, EventArgs e) =>
{
CloseListEvent?.Invoke(ControlId);
CloseSelectEvent?.Invoke(false);
Dispose();
};
buttonSearch.Click += async (object sender, EventArgs e) => { await LoadListAsync(); };
buttonCancelSearch.Click += (object sender, EventArgs e) => { panelSearch.Visible = false; _searchValues?.Clear(); };
dataGridViewList.KeyDown += (object sender, KeyEventArgs e) =>
{
switch (e.KeyCode)
{
case Keys.Insert:
if (toolStripButtonAdd.Visible)
{
AddElement();
}
break;
case Keys.Enter:
if (toolStripButtonUpd.Visible)
{
UpdElement();
}
break;
case Keys.Delete:
if (toolStripButtonDel.Visible)
{
DelElement();
}
break;
}
};
dataGridViewList.CellDoubleClick += (object sender, DataGridViewCellEventArgs e) =>
{
if (_openMode == ControlOpenMode.Select && dataGridViewList.SelectedRows.Count > 0)
{
SelectElement();
}
UpdElement();
};
toolStripButtonPrev.Click += async (object sender, EventArgs e) =>
{
if (int.TryParse(toolStripTextBoxPage.Text, out int page))
{
toolStripTextBoxPage.Text = (page - 1).ToString();
await LoadListAsync();
}
};
toolStripButtonNext.Click += async (object sender, EventArgs e) =>
{
if (int.TryParse(toolStripTextBoxPage.Text, out int page))
{
toolStripTextBoxPage.Text = (page + 1).ToString();
await LoadListAsync();
}
};
toolStripTextBoxPage.KeyDown += async (object sender, KeyEventArgs e) =>
{
if (e.KeyData == Keys.Enter)
{
await LoadListAsync();
}
};
toolStripComboBoxPageNames.SelectedIndexChanged += async (object sender, EventArgs e) => { await LoadListAsync(); };
}
/// <summary>
/// Вызов события загрузки данных на datagrid
/// </summary>
private async Task LoadListAsync()
{
var cursor = Cursor.Current;
var selectedGuids = new List<Guid>();
foreach (DataGridViewRow row in dataGridViewList.SelectedRows)
{
selectedGuids.Add(new Guid(row.Cells[0].Value.ToString()));
}
L data = null;
try
{
Cursor.Current = Cursors.WaitCursor;
if (panelSearch.Visible)
{
var controls = panelSearchControls.Controls.Cast<IBaseControl>();
if (_searchValues == null)
{
_searchValues = new();
}
_searchValues.Clear();
foreach (var cntrl in controls)
{
_searchValues.Add((cntrl.GetPropertyName(), cntrl.GetValueFromControl()));
}
}
if (ParentPropertyName.IsNotEmpty())
{
if (ParentId.HasValue)
{
await Task.Run(() => data = GetDataFromParent(ParentId.Value));
Visible = true;
}
else
{
Visible = false;
}
}
// если включена пагинация
else if (toolStripFooter.Visible)
{
// постраничная
if (toolStripTextBoxPage.Visible)
{
if (int.TryParse(toolStripTextBoxPage.Text, out int page) && int.TryParse(toolStripTextBoxCountRecords.Text.ToString(), out int count))
{
await Task.Run(() => data = GetDataWithPageNumber(page - 1, count));
}
}
// поименная
else if (toolStripComboBoxPageNames.Visible)
{
if (toolStripComboBoxPageNames.SelectedItem is PageNamesForPaginationModel key)
{
await Task.Run(() => data = GetDataWithPageName(key.Key));
}
}
}
else
{
await Task.Run(() => data = GetData());
}
toolStripLabelCountPages.Text = $"из {data?.MaxCount}";
}
catch (Exception ex)
{
if (_businessLogic.Errors.Count > 0)
{
DialogHelper.MessageException(_businessLogic.Errors, "Ошибки при получении данных");
}
else
{
DialogHelper.MessageException(ex.Message, "Ошибка при получении данных");
}
}
finally
{
Cursor.Current = cursor;
}
FillDataOnGridAsync(data?.List, selectedGuids);
}
/// <summary>
/// Заполнение таблицы
/// </summary>
/// <param name="data"></param>
private void FillDataOnGridAsync(List<E> data, List<Guid> selectedGuids)
{
if (data == null)
{
return;
}
dataGridViewList.Rows.Clear();
foreach (var elem in data)
{
var mas = new List<object>();
foreach (DataGridViewColumn column in dataGridViewList.Columns)
{
mas.Add(elem.GetType().GetProperty(column.Name["Column".Length..])?.GetValue(elem));
}
dataGridViewList.Rows.Add(mas.ToArray());
dataGridViewList.Rows[^1].Selected = selectedGuids.Contains(new Guid(mas[0].ToString()));
}
if (selectedGuids.Count == 0 && dataGridViewList.Rows.Count > 0)
{
dataGridViewList.Rows[0].Selected = true;
}
}
/// <summary>
/// Вызов события при добавлении элемента
/// </summary>
private void AddElement() => LaunchControl(null);
/// <summary>
/// Вызов события при изменении элемента
/// </summary>
private void UpdElement()
{
foreach (DataGridViewRow selected in dataGridViewList.SelectedRows)
{
LaunchControl(new Guid(selected.Cells[0].Value.ToString()));
}
}
/// <summary>
/// Вызов события при удалении элемента
/// </summary>
private async void DelElement()
{
if (MessageBox.Show("Удалить выбранные записи?", "Подтверждение", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
var cursor = Cursor.Current;
try
{
Cursor.Current = Cursors.WaitCursor;
foreach (DataGridViewRow selected in dataGridViewList.SelectedRows)
{
_businessLogic.Delete(new G { Id = new Guid(selected.Cells[0].Value.ToString()) });
}
}
catch (Exception ex)
{
if (_businessLogic.Errors.Count != 0)
{
DialogHelper.MessageException(_businessLogic.Errors, "Ошибки при удалении");
}
else
{
DialogHelper.MessageException(ex.Message, "Ошибки при удалении");
}
}
finally
{
Cursor.Current = cursor;
await LoadListAsync();
}
}
}
/// <summary>
/// Вызов события при выборе элемента
/// </summary>
private void SelectElement()
{
try
{
SelectedId = new Guid(dataGridViewList.SelectedRows[0].Cells[0].Value.ToString());
SelectedText = _businessLogic.GetElement(new G { Id = SelectedId })?.ToString();
CloseSelectEvent?.Invoke(true);
Dispose();
}
catch (Exception ex)
{
DialogHelper.MessageException(ex.Message, "Ошибка при получении выбранного значения");
}
}
/// <summary>
/// Создание формы с контролом для работы с элементом
/// </summary>
/// <param name="id"></param>
private void LaunchControl(Guid? id)
{
try
{
var control = ControlViewEntityElement.GetInstance() as IControlChildEntity;
if (ParentId.HasValue)
{
control.ParentId = ParentId;
control.ParentPropertyName = ParentPropertyName;
}
if (toolStripFooter.Visible && toolStripComboBoxPageNames.Visible)
{
if (toolStripComboBoxPageNames.SelectedItem is PageNamesForPaginationModel key)
{
control.ParentId = new Guid(key.Key);
control.ParentPropertyName = toolStripComboBoxPageNames.Tag?.ToString();
}
}
var form = new Form
{
Text = (id.HasValue ? $"{Title}. Редактирование" : $"{Title}. Добавление"),
StartPosition = FormStartPosition.CenterScreen,
ControlBox = false
};
control.Open( new ControlOpenModel
{
OpenMode = ControlOpenMode.List,
ElementId = id,
CloseElement = async (Guid id) =>
{
await LoadListAsync();
form.Close();
}
});
form.Height = (control as UserControl).Height + 55;
form.Width = (control as UserControl).Width + 20;
form.Controls.Add(control as UserControl);
form.Show();
}
catch (Exception ex)
{
DialogHelper.MessageException(ex.Message, "Ошибки при открытии элемента");
}
}
private ControlViewEntityListConfiguration GetConfig() => _genericControlViewEntityList?.GetConfigControl();
private L GetData() => _genericControlViewEntityList?.GetDataForControl();
private L GetDataWithPageName(string key) => _genericControlViewEntityList?.GetDataWithPageNameForControl(key);
private L GetDataWithPageNumber(int page, int count) => _genericControlViewEntityList?.GetDataWithPageNumberForControl(page, count);
private L GetDataFromParent(Guid id) => _genericControlViewEntityList?.GetDataFromParentForControl(id);
}
}