using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Windows.Forms; using System.Xml.Linq; using ToolsDesktop.Enums; using ToolsDesktop.Helpers; using ToolsDesktop.Interfaces; using ToolsDesktop.Models; using ToolsModule.ManagmentDependency; using ToolsModule.ManagmentEntity; using ToolsModule.ManagmentExtension; using ToolsModule.ManagmentSecurity; namespace ToolsDesktop.Controls { public partial class GenericControlEntityList : MainControlViewEntityList, IControlViewEntityList where G : GetBindingModel, new() where S : SetBindingModel, new() where L : ListViewModel where E : ElementViewModel where BL : IGenericEntityLogic { /// /// Режим работы /// private ControlOpenMode _openMode; /// /// Событие, вызываемое при закрытии контрола /// private event Action CloseListEvent; /// /// Событие, вызываемое при закрытии контрола /// private event Action CloseSelectEvent; private readonly object _lockObject = new(); private bool _usePages = false; private bool _useNames = false; /// /// Объект бизнес-логики для получения данных /// protected BL _businessLogic; /// /// Методы для реализации в generic-контроле /// protected IGenericControlEntityList _genericControlViewEntityList; /// /// Констркутор /// public GenericControlEntityList() { InitializeComponent(); InitEvents(); _businessLogic = DependencyManager.Instance.Resolve(); _controlViewEntityList = this; } #region IControlViewEntityList public 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, $"{Title}. Ошибка при конфигурации"); } } if (!model.LazyLoading) { LoadList(); } } 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); 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() }; var elem = toolStripComboBoxPageNames.Items.Cast().FirstOrDefault(x => x.Key == pageName.Key); if (elem != null) { toolStripComboBoxPageNames.SelectedIndexChanged -= ToolStripComboBoxPageNamesSelectedIndexChanged; toolStripComboBoxPageNames.SelectedItem = elem; toolStripComboBoxPageNames.SelectedIndexChanged += ToolStripComboBoxPageNamesSelectedIndexChanged; } } if (config.Element("ParentId").Value.ToString() != "-") { ParentId = new Guid(config.Element("ParentId").Value.ToString()); } LoadList(); } #endregion /// /// Конфигуратор контрола /// /// Настройки 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(); 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, AutoSizeMode = attr.ColumnWidth != 0 ? DataGridViewAutoSizeColumnMode.None : DataGridViewAutoSizeColumnMode.Fill }); if (attr.DefaultCellStyleFormat.IsNotEmpty()) { dataGridViewList.Columns[colIndex].DefaultCellStyle.Format = attr.DefaultCellStyleFormat; } } } 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); ToolStripMenuItem itemContext = new() { Text = elem.Value.Title, Name = elem.Key }; itemContext.Click += elem.Value.Event; contextMenuStripDataGrid.Items.Add(itemContext); } } // либо скрытие пункта, если не предусмотренно подпунктов else { toolStripSplitButtonActions.Visible = false; toolStripSeparator5.Visible = false; } toolStripFooter.Visible = config.PaginationOn; // Пагинация if (config.PaginationOn) { // пагинация по страницам if (config.CountElementsOnPage.HasValue) { _usePages = true; toolStripTextBoxCountRecords.Text = config.CountElementsOnPage.Value.ToString(); toolStripLabelPageName.Visible = toolStripComboBoxPageNames.Visible = false; } // пагинация по названиям if (config.PageNamesForPagination != null) { _useNames = true; toolStripButtonPrev.Visible = toolStripLabelPage.Visible = toolStripTextBoxPage.Visible = toolStripLabelCountPages.Visible = toolStripLabelCountRecords.Visible = toolStripTextBoxCountRecords.Visible = toolStripButtonNext.Visible = false; toolStripComboBoxPageNames.Items.AddRange(config.PageNamesForPagination.ToArray()); if (toolStripComboBoxPageNames.Items.Count > 0) { toolStripComboBoxPageNames.SelectedIndexChanged -= ToolStripComboBoxPageNamesSelectedIndexChanged; toolStripComboBoxPageNames.SelectedIndex = 0; toolStripComboBoxPageNames.SelectedIndexChanged += ToolStripComboBoxPageNamesSelectedIndexChanged; } toolStripComboBoxPageNames.Tag = config.ParentPropertyName; } } // при вызове контрола для выбора элемента, делаем возможность выбора только одной записи dataGridViewList.MultiSelect = _openMode == ControlOpenMode.List; // Открытие через родительский элемент if (_openMode == ControlOpenMode.Child) { dataGridViewList.MultiSelect = true; panelHeader.Visible = false; toolStripButtonClose.Visible = false; toolStripSeparator6.Visible = false; toolStripButtonSelect.Visible = false; } // Открытие через родительский элемент if (_openMode == ControlOpenMode.Select) { toolStripSeparator6.Visible = true; toolStripButtonSelect.Visible = true; } Dock = DockStyle.Fill; } /// /// Инициализация событий к контролам /// 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; }; toolStripButtonRef.Click += (object sender, EventArgs e) => { LoadList(); }; toolStripButtonSelect.Click += (object sender, EventArgs e) => { SelectElement(); }; toolStripButtonClose.Click += (object sender, EventArgs e) => { CloseListEvent?.Invoke(ControlId); CloseSelectEvent?.Invoke(false); Dispose(); }; buttonSearch.Click += (object sender, EventArgs e) => { LoadList(); }; buttonCancelSearch.Click += (object sender, EventArgs e) => { panelSearch.Visible = false; LoadList(); }; 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 += (object sender, EventArgs e) => { if (int.TryParse(toolStripTextBoxPage.Text, out int page)) { toolStripTextBoxPage.Text = (page - 1).ToString(); LoadList(); } }; toolStripButtonNext.Click += (object sender, EventArgs e) => { if (int.TryParse(toolStripTextBoxPage.Text, out int page)) { toolStripTextBoxPage.Text = (page + 1).ToString(); LoadList(); } }; toolStripTextBoxPage.KeyDown += (object sender, KeyEventArgs e) => { if (e.KeyData == Keys.Enter) { LoadList(); } }; toolStripComboBoxPageNames.SelectedIndexChanged += ToolStripComboBoxPageNamesSelectedIndexChanged; } /// /// Событие смены выбрарнного элемента выпдающего спика (вынесено отдельно, чтобы при настройки конфигурации не вызывать прогрузку) /// /// /// private void ToolStripComboBoxPageNamesSelectedIndexChanged(object sender, EventArgs e) => LoadList(); /// /// Вызов события загрузки данных на datagrid /// private void LoadList() { var cursor = Cursor.Current; var selectedGuids = new List(); foreach (DataGridViewRow row in dataGridViewList.SelectedRows) { selectedGuids.Add(new Guid(row.Cells[0].Value.ToString())); } L data = null; try { Cursor.Current = Cursors.WaitCursor; var model = new G(); if (panelSearch.Visible) { var controls = panelSearchControls.Controls.Cast(); foreach (var cntrl in controls) { var prop = typeof(G).GetProperty(cntrl.GetPropertyName()); if (prop != null) { prop.SetValue(model, cntrl.GetValueFromControl()); } } } if (ParentPropertyName.IsNotEmpty()) { if (ParentId.HasValue) { var prop = typeof(G).GetProperty(ParentPropertyName); if (prop != null) { prop.SetValue(model, ParentId); } Visible = true; } else { Visible = false; } } // если включена пагинация // постраничная if (_usePages) { if (int.TryParse(toolStripTextBoxPage.Text, out int page) && int.TryParse(toolStripTextBoxCountRecords.Text.ToString(), out int count)) { model.PageNumber = page - 1; model.PageSize = count; } } // поименная if (_useNames) { if (toolStripComboBoxPageNames.SelectedItem is PageNamesForPaginationModel key) { var prop = typeof(G).GetProperty(toolStripComboBoxPageNames.Tag.ToString()); if (prop != null) { prop.SetValue(model, key.Key); } } } data = _businessLogic.GetList(model); if (data == null && _businessLogic.Errors.Count > 0) { DialogHelper.MessageException(_businessLogic.Errors, $"{Title}. Ошибки при получении данных"); return; } toolStripLabelCountPages.Text = $"из {data?.MaxCount}"; } catch (Exception ex) { if (_businessLogic.Errors.Count > 0) { DialogHelper.MessageException(_businessLogic.Errors, $"{Title}. Ошибки при получении данных"); } else { DialogHelper.MessageException(ex.Message, $"{Title}. Ошибка при получении данных"); } } finally { Cursor.Current = cursor; } FillDataOnGrid(data?.List, selectedGuids); } /// /// Заполнение таблицы /// /// private void FillDataOnGrid(List data, List selectedGuids) { if (data == null) { return; } if (dataGridViewList.Columns.Count == 0) { return; } dataGridViewList.Rows.Clear(); foreach (var elem in data) { var mas = new List(); 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; } } /// /// Вызов события при добавлении элемента /// private void AddElement() => LaunchControl(null); /// /// Вызов события при изменении элемента /// private void UpdElement() { foreach (DataGridViewRow selected in dataGridViewList.SelectedRows) { LaunchControl(new Guid(selected.Cells[0].Value.ToString())); } } /// /// Вызов события при удалении элемента /// private 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, $"{Title}. Ошибки при удалении"); } else { DialogHelper.MessageException(ex.Message, $"{Title}. Ошибки при удалении"); } } finally { Cursor.Current = cursor; LoadList(); } } } /// /// Вызов события при выборе элемента /// 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, $"{Title}. Ошибка при получении выбранного значения"); } } /// /// Создание формы с контролом для работы с элементом /// /// private void LaunchControl(Guid? id) { try { var control = ControlViewEntityElement.GetInstance() as IControlChildEntity; if (ParentId.HasValue) { control.ParentId = ParentId; control.ParentPropertyName = ParentPropertyName; } else if (toolStripFooter.Visible && toolStripComboBoxPageNames.Visible) { if (toolStripComboBoxPageNames.SelectedItem is PageNamesForPaginationModel key) { if (key.Key.GetType().Name == "Guid") { control.ParentId = new Guid(key.Key.ToString()); } 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 = (Guid id) => { LoadList(); 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, $"{Title}. Ошибки при открытии элемента"); } } /// /// Получение настроек для контрола /// /// private ControlViewEntityListConfiguration GetConfig() => _genericControlViewEntityList?.GetConfigControl(); /// /// Получение списка идентификаторов выбранных записей /// /// protected List GetSelectedIds() { List guids = new(); foreach (DataGridViewRow selected in dataGridViewList.SelectedRows) { guids.Add(new Guid(selected.Cells[0].Value.ToString())); } return guids; } } }