using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; namespace Volian.Controls.Library { //C2025-023 Electronic Procedures //Control for designating which cells in a table require EP input public partial class TablePropertiesControl : UserControl { //defines the type of possible inputs from an EP viewer public enum EPinputtype { none, textbox, checkbox }; private DataTable values; private BindingSource bindingSource = null; private int totalrows = 1; private int totalcols = 1; public readonly string epname; private bool IsInitializing; //initialization / data will be in the format: // totalnumrows,totalnumcols;(row,col):value|(row,col):value... public TablePropertiesControl(string name, string title, string initialvalues) { InitializeComponent(); IsInitializing = true; epname = name; lbltitle.Text = title; initializevalues(initialvalues); bindingSource = new BindingSource(values, ""); dataview.DataSource = bindingSource; dataview.AutoGenerateColumns = false; Load += new EventHandler(FormLoad_setDefaults); } //initialization / data will be in the format: // totalnumrows,totalnumcols;(row,col):value|(row,col):value... private void initializevalues(string initialvalues) { values = new DataTable("values"); if (!string.IsNullOrEmpty(initialvalues)) { string[] grp = initialvalues.Split(';'); string[] total = grp[0].Split(','); initializedt(int.Parse(total[0]), int.Parse(total[1])); string[] ivs = grp[1].Split('|'); //pair will be of format: //(row,col):value foreach (string pair in ivs) { Match m = Regex.Match(pair, @"\(([\d]),([\d])\):([\w]+)"); if (m.Success) { int row = int.Parse(m.Groups[1].Value); int col = int.Parse(m.Groups[2].Value); string v = m.Groups[3].Value; values.Rows[row][col] = v; } } values.AcceptChanges(); } else { initializedt(1, 1); } } //initialize the blank datatable private void initializedt(int numrows, int numcols) { totalrows = numrows; totalcols = numcols; for (int c = 0; c < totalcols; c++) { values.Columns.Add(new DataColumn($"Column{c}") { DefaultValue = "none" }); } for (int rw = 0; rw < totalrows; rw++) { values.Rows.Add(); } } void FormLoad_setDefaults(object sender, EventArgs e) { BindingSource bindingSourceDropDown = new BindingSource(); bindingSourceDropDown.DataSource = Enum.GetNames(typeof(EPinputtype)); //in order to achieve a dropdown of possible values need //to remove the auto-inserted columns //that were auto-generated of type type text //when values was bound to the datagrid for (int c = 0; c < totalcols; c++) { dataview.Columns.RemoveAt(c); var cName = new DataGridViewComboBoxColumn(); cName.DataSource = bindingSourceDropDown; cName.DefaultCellStyle.NullValue = "none"; dataview.Columns.Insert(c, cName); } NumRows.Value = totalrows; NumCols.Value = totalcols; IsInitializing = false; setDataViewtoValues(); } //set the display cells to match the values in the datatable for initialization //and resize of the dataviewgrid void setDataViewtoValues() { if (!IsInitializing) { for (int c = 0; c < totalcols; c++) { for (int rw = 0; rw < totalrows; rw++) { dataview.Rows[rw].Cells[c].Value = values.Rows[rw][c]; } } } } //Get storage string for storing table values in db // data will be returned in the format: // totalnumrows,totalnumcols;(row,col):value|(row,col):value... public string GetStorageValue() { //force any in progress editing to commit. ((BindingSource)dataview.DataSource).EndEdit(); StringBuilder bldr = new StringBuilder(); bldr.Append($"{totalrows},{totalcols}"); List points = new List(); for (int rw = 0; rw < values.Rows.Count; rw++) { for (int col = 0; col < values.Columns.Count; col++) { if ((string) values.Rows[rw][col] != "none") points.Add($"({rw},{col}):{values.Rows[rw][col]}"); } } if (points.Count > 0) { bldr.Append(";"); bldr.Append(string.Join("|", points)); } return bldr.ToString(); } private void NumRows_ValueChanged(object sender, EventArgs e) { int endNumRows = (int)NumRows.Value; int curNumRows = totalrows; //remove rows till equal while (curNumRows > endNumRows) { values.Rows.RemoveAt(curNumRows - 1); curNumRows--; } //add rows till equal while (curNumRows < endNumRows) { values.Rows.Add(); curNumRows++; } totalrows = endNumRows; setDataViewtoValues(); } private void NumCols_ValueChanged(object sender, EventArgs e) { int endNumCols = (int)NumCols.Value; int curNumCols = totalcols; BindingSource bindingSourceDropDown = new BindingSource(); bindingSourceDropDown.DataSource = Enum.GetNames(typeof(EPinputtype)); //remove cols till equal while (curNumCols > endNumCols) { values.Columns.RemoveAt(curNumCols - 1); dataview.Columns.RemoveAt(curNumCols - 1); curNumCols--; } //add cols till equal while (curNumCols < endNumCols) { values.Columns.Add(new DataColumn($"Column{curNumCols + 1}") { DefaultValue = "none"}); if (dataview.Columns.Count > curNumCols) dataview.Columns.RemoveAt(curNumCols); var cName = new DataGridViewComboBoxColumn(); cName.DataSource = bindingSourceDropDown; cName.DefaultCellStyle.NullValue = "none"; dataview.Columns.Add(cName); curNumCols++; } totalcols = endNumCols; setDataViewtoValues(); } //set the datatable value to match the changed datagridview value //for some reason despite being bound, does not automatically update // (it may be that datatable as a bindingsource does not implement INotifyProperty // and thus needs manually set like this) private void dataview_CellEndEdit(object sender, DataGridViewCellEventArgs e) { values.Rows[e.RowIndex][e.ColumnIndex] = (string) dataview.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; } } }