I'm trying to allow the user to upload existing information to a data table. Here's what the code is for the upload:
private void label30_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
StreamReader read = new StreamReader(File.OpenRead(ofd.FileName));
string[] lines = File.ReadAllLines(ofd.FileName);
string[] values;
for (int i = 31; i < lines.Length; i++)
{
values = lines[i].ToString().Split(',');
string[] row = new string[values.Length];
for (int j = 0; j < values.Length; j++)
{
row[j] = values[j].Trim();
}
stkSheetdgv.Rows.Add(row);
read.Close();
read.Dispose();
}
}
}
There is a lot of other information inside the text file, hence the reason int i = 31. I'm getting System.InvalidOperationException: 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.'
Can someone tell me what is missing to make this work? I can add more code for the dt if necessary. Let me know.
stkSheetdgv.AutoGenerateColumns = false;
DataTable dt = new DataTable();
dt.Columns.Add("Wire", typeof(String));
dt.Columns.Add("Pole", typeof(String));
dt.Columns.Add("Primary Unit", typeof(String));
dt.Columns.Add("Down Guy", typeof(String));
dt.Columns.Add("Anchor", typeof(String));
dt.Columns.Add("Transformer", typeof(String));
dt.Columns.Add("Ground", typeof(String));
dt.Columns.Add("Riser/Disconnect", typeof(String));
dt.Columns.Add("Misc.", typeof(String));
DataGridViewComboBoxColumn wire = new DataGridViewComboBoxColumn();
var wirelist = new List<string>() {"AAC 1/0 POPPY", "AAC 477 COSMOS"};
wire.DataSource = wirelist;
wire.HeaderText = "Wire";
wire.DataPropertyName = "Wire";
DataGridViewComboBoxColumn pole = new DataGridViewComboBoxColumn();
var polelist = new List<string>() {"30C4 CCA", "30C5 CCA"};
pole.DataSource = polelist;
pole.HeaderText = "Pole";
pole.DataPropertyName = "Pole";
DataGridViewComboBoxColumn primary = new DataGridViewComboBoxColumn();
var primarylist = new List<string>() {"C1-LD", "C2-LD"};
primary.DataSource = primarylist;
primary.HeaderText = "Primary Unit";
primary.DataPropertyName = "Primary Unit";
DataGridViewComboBoxColumn down = new DataGridViewComboBoxColumn();
var downlist = new List<string>() {"E1-5-144", "E1-5-144P"};
down.DataSource = downlist;
down.HeaderText = "Down Guy";
down.DataPropertyName = "Down Guy";
DataGridViewComboBoxColumn anch = new DataGridViewComboBoxColumn();
var anchlist = new List<string>() {"F1-2 Expansion", "F1-2 Plate"};
anch.DataSource = anchlist;
anch.HeaderText = "Anchor";
anch.DataPropertyName = "Anchor";
DataGridViewComboBoxColumn trans = new DataGridViewComboBoxColumn();
var translist = new List<string>() { "G311-15kVA", "G311-25kVA"};
trans.DataSource = translist;
trans.HeaderText = "Transformer";
trans.DataPropertyName = "Transformer";
DataGridViewComboBoxColumn ground = new DataGridViewComboBoxColumn();
var groundlist = new List<string>() { "M2-12", "M2-11" };
ground.DataSource = groundlist;
ground.HeaderText = "Ground";
ground.DataPropertyName = "Ground";
DataGridViewComboBoxColumn rise = new DataGridViewComboBoxColumn();
var riserlist = new List<string>() { "M8-60-10'", "M8-100-10'"};
rise.DataSource = riserlist;
rise.HeaderText = "Riser/Disconnect";
rise.DataPropertyName = "Riser/Disconnect";
DataGridViewComboBoxColumn misc = new DataGridViewComboBoxColumn();
var misclist = new List<string>() { "M5-5LD", "M5-5HD"};
misc.DataSource = misclist;
misc.HeaderText = "Misc.";
misc.DataPropertyName = "Misc.";
stkSheetdgv.DataSource = dt;
stkSheetdgv.Columns.AddRange(wire, pole, primary, down, anch, trans, ground, rise, misc);
stkSheetdgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
There are two different ways to resolve this issue, either by removing the assignment of the DataSource (e.g. remove stkSheetdgv.DataSource = dt;) on the DataGridView, or adding to the DataSource explicitly:
Code
private void label30_Click(object sender, EventArgs e)
{
DataTable dataTable = (DataTable)stkSheetdgv.DataSource;
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
using (StreamReader read = new StreamReader(File.OpenRead(ofd.FileName)))
{
string[] lines = File.ReadAllLines(ofd.FileName);
string[] values;
for (int i = 31; i < lines.Length; i++)
{
values = lines[i].ToString().Split(',');
var dataRow = dataTable.NewRow();
for (int j = 0; j < values.Length; j++)
{
dataRow[j] = values[j].Trim();
}
dataTable.Rows.Add(dataRow);
dataTable.AcceptChanges();
}
}
}
}
Edit
The reason that you're receiving the error is due to the csv having more columns than specified on the DataTable. The CSV file that I used was:
AAC 1/0 POPPY,30C4 CCA,C1-LD,E1-5-144,F1-2 Expansion,G311-15kVA,M2-12,M8-60-10',M5-5LD
AAC 477 COSMOS,30C5 CCA,C2-LD,E1-5-144P,F1-2 Plate,G311-25kVA,M2-11,M8-100-10',M5-5HD
Which worked perfectly fine for me.
Related
what i want is my combobox to be loaded in the 1st row of my DataGrid and my header consist of checkboxes
ObservableCollection<dynamic> items = new ObservableCollection<dynamic>();
private IEnumerable<string> PropertyNames; //Store the properties names of the dynamic object
//First i am reading my dt through Excel;
DataSet result = new DataSet();
DataTable dt = new DataTable();
if (fileName.EndsWith(".xlsx"))
{
// Reading from a binary Excel file (format; *.xlsx)
FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
result = excelReader.AsDataSet();
dt = result.Tables[0];
excelReader.Close();
}
if (fileName.EndsWith(".xls"))
{
// Reading from a binary Excel file ('97-2003 format; *.xls)
FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
result = excelReader.AsDataSet();
excelReader.Close();
}
// Then i am creating my header as shown in the attachment as per my dt column count
for (int i = 0; i < dt.Columns.Count; i++)
{
DataGridTextColumn checkBoxColumn = new DataGridTextColumn();
System.Windows.Controls.CheckBox headerCheckBox = new System.Windows.Controls.CheckBox();
headerCheckBox.Content = "UnNamedColumn" + i;
checkBoxColumn.Header = headerCheckBox;
checkBoxColumn.Binding = new System.Windows.Data.Binding(dt.Rows[0][i].ToString());
dataGrid.Columns.Add(checkBoxColumn);
}
// I am trying to load combobox in the 1st row of the DataGrid
PropertyNames = new List<string>();
items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
if (i == 0)
{
dynamic item = new DynamicObjectClass();
for (int j = 0; j < dt.Columns.Count; j++)
{
// DataGridColumn columns = GetNewComboBoxColumn("UnNamedColumn" + j, dt.Rows[0][j].ToString(), binddt)
var cb = new System.Windows.Controls.ComboBox();
cb.ItemsSource = new List<string> { "C50", "C40", "C30" };
cb.SelectedItem = new System.Windows.Data.Binding(dt.Rows[0][j].ToString());
item.TrySetMember(new SetPropertyBinder(dt.Rows[0][j].ToString()), cb);
}
PropertyNames = item.GetDynamicMemberNames();
items.Add(item);
dataGrid.ItemsSource = items;
break;
}
}
// And at last i am appending the whole dt in datagrid
for (int i = 0; i < dt.Rows.Count; i++)
{
dynamic item = new DynamicObjectClass();
for (int j = 0; j < dt.Columns.Count; j++)
{
item.TrySetMember(new SetPropertyBinder(dt.Rows[0][j].ToString()), dt.Rows[i][j].ToString());
}
PropertyNames = item.GetDynamicMemberNames();
items.Add(item);
dataGrid.ItemsSource = items;
}
You can do the following and replace the List by your data:
var bindingSource = new BindingSource();
bindingSource.DataSource = new List<string> { "C50", "C40", "C30" };
comboBox1.DataSource = bindingSource.DataSource;
comboBox1.DisplayMember = new System.Windows.Data.Binding(dt.Rows[0][j].ToString());
comboBox1.ValueMember = new System.Windows.Data.Binding(dt.Rows[0][j].ToString());
source: How to bind a List to a ComboBox?
I've two comboboxes in a form, the first combobox display each "mark" of truck and second may display the models of each "mark". For example if mark is volvo the second combobox may display "FH, FH6 ...", otherwise if mark is "MAN" the second combobox may display "TGX, TGX 38" ...
I've try to do a cycle to refesh my second combobox, each time, that the first combobox is changed.
while (comboBox1.SelectedIndex == -1)
{
comboBox2.Items.Clear();
if (comboBox1.SelectedIndex == 1)
{
comboBox2.DisplayMember = "Modelo";
comboBox2.DataSource = d.Tables["Modelos-MAN"].DefaultView;
}
if (comboBox1.SelectedIndex == 2)
{
comboBox2.DisplayMember = "ModeloV";
comboBox2.DataSource = d.Tables["Modelos-VOLVO"].DefaultView;
comboBox2.Refresh();
}
}
if (comboBox1.SelectedIndex==1)
{
comboBox2.DisplayMember = "Modelo";
comboBox2.DataSource = d.Tables["Modelos-MAN"].DefaultView;
}
if(comboBox1.SelectedIndex == 2)
{
comboBox2.DisplayMember = "ModeloV";
comboBox2.DataSource = d.Tables["Modelos-VOLVO"].DefaultView;
comboBox2.Refresh();
}
Happens that if i select "MAN", it shows "MAN" models and then if i change, and select "Volvo", the second combobox show me "System.Data.DataRowView".
What is happening?How i can solve this?
Note: I've also, a method to generate truck "mark" and "models":
public DataSet LoadMarkAndModel()
{
var marcas = new string[6];
marcas[0] = "Marca ...";
marcas[1] = "MAN";
marcas[2] = "Volvo";//Linha 2 coluna 2
marcas[3] = "DAF";
marcas[4] = "Renault";//Linha 4 coluna 2
marcas[5] = "Mercedes-Benz";
var modelosMAN = new string[7];
var modelosVolvo = new string[5];
modelosMAN[0] = "TGX";
modelosMAN[1] = "TGX D38";
modelosMAN[2] = "TGX EfficientLine 2";
modelosMAN[3] = "TGS";
modelosMAN[4] = "TGA";
modelosMAN[5] = "TGA-WW";
modelosMAN[6] = "TGM";
modelosVolvo[0] = "FH16";
modelosVolvo[1] = "FH";
modelosVolvo[2] = "FM";
modelosVolvo[3] = "FE";
modelosVolvo[4] = "FL";
DataSet data = new DataSet("DataSetOfTrucks");
DataTable table = new DataTable("Marcas");
DataColumn colunaID = new DataColumn("ID", typeof(int));
DataColumn colunaMarca = new DataColumn("Marca", typeof(string));
//table.Columns.Add("Description", typeof(string));
table.Columns.Add(colunaID);
table.Columns.Add(colunaMarca);
for (int i = 0; i < marcas.Length; i++)
{
DataRow manyMark = table.NewRow();
manyMark["ID"] = i + 1;
manyMark["Marca"] = marcas[i];
table.Rows.Add(manyMark);
}
data.Tables.Add(table);
DataTable modelsTable = new DataTable("Modelos-MAN");
DataColumn modelsIDParent = new DataColumn("IDP", typeof(int));
DataColumn modelo = new DataColumn("Modelo", typeof(string));
modelsTable.Columns.Add(modelsIDParent);
modelsTable.Columns.Add(modelo);
int m = 0;
while (m<modelosMAN.Length)
{
DataRow manyModelsMAN = modelsTable.NewRow();
manyModelsMAN["IDP"] = 1;
manyModelsMAN["Modelo"] = modelosMAN[m];
modelsTable.Rows.Add(manyModelsMAN);
m++;
//if (m > modelosMAN.Length)
// break;
}
data.Tables.Add(modelsTable);
////vOLVO
DataTable modelsTableVOLVO = new DataTable("Modelos-VOLVO");
DataColumn modelsIDParentVOLVO = new DataColumn("IDPVolvo", typeof(int));
DataColumn modeloVolvo = new DataColumn("ModeloV", typeof(string));
modelsTableVOLVO.Columns.Add(modelsIDParentVOLVO);
modelsTableVOLVO.Columns.Add(modeloVolvo);
int count = 0;
while (count < modelosVolvo.Length)
{
DataRow manyModelsVolvo = modelsTableVOLVO.NewRow();
manyModelsVolvo["IDPVolvo"] = 2;
manyModelsVolvo["ModeloV"] = modelosVolvo[count];
modelsTableVOLVO.Rows.Add(manyModelsVolvo);
count++;
}
data.Tables.Add(modelsTableVOLVO);
return data;
}
comboBox1_SelectedIndexChanged()
{
comboBox2.DataSource =null;
if (comboBox1.SelectedIndex==1)
{
comboBox2.DataSource = d.Tables["Modelos-MAN"];
comboBox2.ValueMember="Modelo";
comboBox2.DisplayMember = "Modelo";
}
if(comboBox1.SelectedIndex == 2)
{
comboBox2.DataSource = d.Tables["Modelos-VOLVO"];
comboBox2.DisplayMember = "ModeloV";
comboBox2.ValueMember = "ModeloV";
}
}
I have few DataGrids in my form, and my data source is CSV Files in which I already set the columns to show. In short, when I select New Project, CSV Files is loaded from default location and shows a grid with empty rows and column names.
Now what I want to do is add a dropdownlist (combo box) control for Column 1, which in case of empty grid, remain empty, and in case of CSV file with Data, shows the data dynamically, but I am clueless how to do it. I never added a combobox in grid. All the examples, inlcuding MSDN are more than confusing.
I am newbie and clear answers are more than welcome.
Here is the code, how I am loading CSV Data
string[] strColumns = null;
string[] strData = null;
StreamReader sr = new StreamReader(strCSV);
DataTable dt = null;
int RowCount = 0;
while (!sr.EndOfStream)
{
String strRow = sr.ReadLine().Trim();
if (strRow.Length > 0)
{
strData = strRow.Split(delimter);
if (RowCount == 0)
{
RowCount = 1;
strColumns = strRow.Split(delimter);
dt = new DataTable();
foreach (string csvcolumn in strColumns)
{
DataColumn column = new DataColumn(csvcolumn.ToUpper(), typeof(string));
column.DefaultValue = string.Empty;
dt.Columns.Add(column);
}
}
else
{
DataRow row = dt.NewRow();
for (int i = 0; i < strColumns.Length; i++)
{
row[strColumns[i]] = strData[i] == null ? string.Empty : strData[i].ToString();
}
dt.Rows.Add(row);
}
}
}
sr.Close();
sr.Dispose();
return dt;
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.ColumnCount = 3;
dataGridView1.Columns[0].Name = "Product ID";
dataGridView1.Columns[1].Name = "Product Name";
dataGridView1.Columns[2].Name = "Product Price";
string[] row = new string[] { "1", "Product 1", "1000" };
dataGridView1.Rows.Add(row);
row = new string[] { "2", "Product 2", "2000" };
dataGridView1.Rows.Add(row);
row = new string[] { "3", "Product 3", "3000" };
dataGridView1.Rows.Add(row);
row = new string[] { "4", "Product 4", "4000" };
dataGridView1.Rows.Add(row);
DataGridViewComboBoxColumn cmb = new DataGridViewComboBoxColumn();
cmb.HeaderText = "Select Data";
cmb.Name = "cmb";
cmb.MaxDropDownItems = 4;
cmb.Items.Add("True");
cmb.Items.Add("False");
dataGridView1.Columns.Add(cmb);
}
}
DataGridViewComboBoxCell comboJob = new DataGridViewComboBoxCell();
//these data will be displayed in comboBox:
string[] data = JobIdList.ToArray();
comboJob.Items.AddRange(data);
this.dgInfo()[e.ColumnIndex, e.RowIndex] = comboJob;
bValidating = true;
I have a winform in c# that I dynamically created two comboboxes and a textbox. When a user selects say the month and year and enters a value in the text box I want get the related comboboxes values when the button is clicked to save. By default the month and year combobox will have the current month and year selected.
There is also another part in the same screen where data will be populated for the previous month like Jan to March for the current year in the comboboxes and the text boxes if available.
I am not sure whether this approach is correct or I should go with a datagridview. Below is the screenshot and my code. Any suggestions on how I can do this.
Screenshot
Code
private void createComboMonths()
{
int width = 79;
int height = 24;
int spacing = 28;
ComboBox[] SubMonths = new ComboBox[12];
for (int i = 0; i <= 11; ++i)
{
SubMonths[i] = new ComboBox();
SubMonths[i].Name = "SubMonths";
SubMonths[i].DropDownStyle = ComboBoxStyle.DropDownList;
SubMonths[i].Size = new Size(width, height);
SubMonths[i].Location = new Point(56, (i * height) + spacing);
SubMonths[i].Items.Add("January");
SubMonths[i].Items.Add("February");
SubMonths[i].Items.Add("March");
SubMonths[i].Items.Add("April");
SubMonths[i].Items.Add("May");
SubMonths[i].Items.Add("June");
SubMonths[i].Items.Add("July");
SubMonths[i].Items.Add("August");
SubMonths[i].Items.Add("September");
SubMonths[i].Items.Add("October");
SubMonths[i].Items.Add("November");
SubMonths[i].Items.Add("December");
SubMonths[i].SelectedItem = DateTime.Today.ToString("MMMM");
plSubscription.Controls.Add(SubMonths[i]);
}
}
private void createComboYears()
{
int width = 79;
int height = 24;
int spacing = 28;
ComboBox[] SubYears = new ComboBox[12];
for (int i = 0; i <= 11; ++i)
{
SubYears[i] = new ComboBox();
SubYears[i].Name = "SubYears";
SubYears[i].DropDownStyle = ComboBoxStyle.DropDownList;
SubYears[i].Size = new Size(width, height);
SubYears[i].Location = new Point(145, (i * height) + spacing);
plSubscription.Controls.Add(SubYears[i]);
fillComboData(SubYears[i]); // Function to fill the last 5 years
}
}
private void createTextBoxes()
{
int width = 79;
int height = 24;
int spacing = 28;
TextBox[] subAmt = new TextBox[12];
for (int i = 0; i <= 11; ++i)
{
subAmt[i] = new TextBox();
subAmt[i].Name = "SubAmt" + i;
subAmt[i].Border.Class = "TextBoxBorder";
subAmt[i].Size = new Size(width, height);
subAmt[i].Margin = new Padding(10, 10, 10, 10);
subAmt[i].Location = new Point(279, (i * height) + spacing);
subAmt[i].KeyPress += new KeyPressEventHandler(txtJanAmt_KeyPress);
plSubscription.Controls.Add(subAmt[i]);
}
}
private void btnSave_Click(object sender, EventArgs e)
{
DataTable dtSubs = new DataTable();
dtSubs.Columns.Add("SubscriberID", typeof(string));
dtSubs.Columns.Add("Month", typeof(string));
dtSubs.Columns.Add("Year", typeof(string));
dtSubs.Columns.Add("SubAmt", typeof(string));
DataRow row = dtSubs.NewRow();
foreach (Control c in plSubscription.Controls)
{
//<- Not sure how do I get the selected row as in the screenshot
}
}
EDIT 1
I used the below code that gets the data from the datatable but not able to do the following
How do I set the value of the comboboxes as selected when I get it from the datatable
For the textbox how do I get the value from the datatable
Whenever there is data available I want that row to be readonly.
Thanks in advance
Changed code
for (int i = 0; i < dt.Rows.Count; i++)
{
#region Grid Column Names
DataGridViewComboBoxColumn mntCmb = new DataGridViewComboBoxColumn();
mntCmb.HeaderText = "Month";
mntCmb.Name = "Month";
mntCmb.DataSource = dt;
mntCmb.DisplayMember = "paidformonth";
mntCmb.ValueMember = "paidformonth";
// <-How do I set the column as selected.
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
yearCmb.DisplayMember = "paidforyear";
yearCmb.ValueMember = "paidforyear";
// <-How do I set the column as selected.
DataGridViewTextBoxColumn amount = new DataGridViewTextBoxColumn();
amount.HeaderText = "Subscription Amount";
amount.Name = "Subscription Amount";
amount.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
// <-How do I set this column with the value from the datatable
#endregion
dgvSubscriptions.Columns.AddRange(mntCmb, yearCmb, amount);
}
Edit 2
I seem to be confused as to why I am getting 3 rows with 6 columns. The datatable only has 2 rows and 3 columns. I am using the above code. I added the ID column just to see what happens. See the screenshot below. I have
dgvSubscriptions.AllowUserToAddRows = true
as I want the user to add rows and enter more data to save. What I am trying to do here is to get a subscription list of months/years that were paid and allow users to add subscription for say May, June assuming Jan to April was paid.
Edit 3
I even set the DataPropertyName instead of the ValueMember still no changes
Edited Code
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
//yearCmb.DataSource = dt;
yearCmb.DisplayMember = "paidforyear";
//yearCmb.ValueMember = "paidforyear";
yearCmb.DataPropertyName= "paidforyear";
yearCmb.DefaultCellStyle.NullValue = dt.Rows[i][2].ToString();
yearCmb.ReadOnly = true;
dgvSubscriptions.Columns.Add(yearCmb);
Edit 4
Below is the actual code that is causing the duplicate columns
dgvSubscriptions.AutoGenerateColumns = false;
dgvSubscriptions.ColumnCount = 1;
dgvSubscriptions.Columns[0].Name = "ID";
dgvSubscriptions.Rows.Clear();
for (int i = 0; i <dt.Rows.Count; i++)
{
dgvSubscriptions.Rows.Add();
#region Grid Column Names
DataGridViewComboBoxColumn mntCmb = new DataGridViewComboBoxColumn();
mntCmb.HeaderText = "Month";
mntCmb.Name = "Month";
//mntCmb.DataSource = dt;
mntCmb.DisplayMember = "paidformonth";
mntCmb.DataPropertyName = "paidformonth";
//mntCmb.ValueMember = "paidformonth";
mntCmb.DefaultCellStyle.NullValue = dt.Rows[i][1].ToString();
mntCmb.ReadOnly = true;
dgvSubscriptions.Columns.Add(mntCmb);
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
//yearCmb.DataSource = dt;
yearCmb.DisplayMember = "paidforyear";
//yearCmb.ValueMember = "paidforyear";
yearCmb.DataPropertyName= "paidforyear";
yearCmb.DefaultCellStyle.NullValue = dt.Rows[i][2].ToString();
yearCmb.ReadOnly = true;
dgvSubscriptions.Columns.Add(yearCmb);
DataGridViewTextBoxColumn amount = new DataGridViewTextBoxColumn();
amount.HeaderText = "Subscription Amount";
amount.Name = "Subscription Amount";
amount.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
//amount.DataPropertyName = dt.Rows[i][2].ToString();
amount.DataPropertyName="subamount";
amount.DefaultCellStyle.NullValue = dt.Rows[i][0].ToString();
amount.ReadOnly = true;
dgvSubscriptions.Columns.Add(amount);
#endregion
}
Edit 5
I used IRSOG code with some modification and below is the full working code.
Working Code
public struct Data
{
public List<string> Mon { get; set; }
public List<string> Year { get; set; }
}
private void fillGridData(DataTable dt)
{
List<string> Mon = new List<string>() { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
List<string> Year = new List<string>();
int CurrentYear = DateTime.UtcNow.Year;
int NextYear = CurrentYear + 1;
int LastFiveYears = CurrentYear - 5;
for (int i = LastFiveYears; i <= NextYear; i++)
{
Year.Add(i.ToString());
}
List<Data> _Data = new List<Data>();
for (int i = 1; i <= 12; i++)
{
_Data.Add(new Data() { Mon = Mon, Year = Year });
}
dgvSubscriptions.Rows.Clear();
dgvSubscriptions.Refresh();
dgvSubscriptions.Visible = true;
dgvSubscriptions.ColumnHeadersDefaultCellStyle.Font = new Font("Trebuchet MS", 8F, FontStyle.Regular);
dgvSubscriptions.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgvSubscriptions.AutoResizeColumns();
dgvSubscriptions.AllowUserToResizeColumns = true;
dgvSubscriptions.AllowUserToOrderColumns = true;
dgvSubscriptions.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dgvSubscriptions.Dock = DockStyle.None;
dgvSubscriptions.BackgroundColor = this.BackColor;
dgvSubscriptions.BorderStyle = BorderStyle.None;
dgvSubscriptions.AllowUserToAddRows = true;
// If dt.Rows.Count > 0 then show the data - do not allow to change existing data
if (dt.Rows.Count > 0)
{
dgvSubscriptions.Rows.Clear();
dgvSubscriptions.Refresh();
#region Grid Column Names
dgvSubscriptions.AutoGenerateColumns = false;
dgvSubscriptions.Rows.Clear();
DataGridViewComboBoxColumn mntCmb = new DataGridViewComboBoxColumn();
mntCmb.HeaderText = "Month";
mntCmb.Name = "Month";
mntCmb.DataSource = Mon;
mntCmb.DefaultCellStyle.NullValue = "";
dgvSubscriptions.Columns.Add(mntCmb);
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
yearCmb.DataSource = Year;
yearCmb.DefaultCellStyle.NullValue = "";
dgvSubscriptions.Columns.Add(yearCmb);
DataGridViewTextBoxColumn amount = new DataGridViewTextBoxColumn();
amount.HeaderText = "Subscription Amount";
amount.Name = "Subscription Amount";
amount.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
amount.DefaultCellStyle.NullValue = "";
dgvSubscriptions.Columns.Add(amount);
#endregion
#region Populate Grid
for (int i = 0; i <dt.Rows.Count; i++)
{
dgvSubscriptions.Rows.Add();
dgvSubscriptions.Rows[i].Cells[0].Value = dt.Rows[i][1].ToString(); // Month
dgvSubscriptions.Rows[i].Cells[0].ReadOnly = true; // do not allow the user to make changes
dgvSubscriptions.Rows[i].Cells[1].Value = dt.Rows[i][2].ToString(); // Year
dgvSubscriptions.Rows[i].Cells[1].ReadOnly = true; // do not allow the user to make changes
dgvSubscriptions.Rows[i].Cells[2].Value = dt.Rows[i][0].ToString(); // Subscription amount
dgvSubscriptions.Rows[i].Cells[2].ReadOnly = true; // do not allow the user to make changes
}
#endregion
}
else // We come here if dt.Rows.Count is 0 we allow the user to select and save
{
#region Grid Column Names
DataGridViewComboBoxColumn mntCmb = new DataGridViewComboBoxColumn();
mntCmb.HeaderText = "Month";
mntCmb.Name = "Month";
mntCmb.DataSource = Mon;
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
yearCmb.DataSource = Year;
DataGridViewTextBoxColumn amount = new DataGridViewTextBoxColumn();
amount.HeaderText = "Subscription Amount";
amount.Name = "Subscription Amount";
amount.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
#endregion
dgvSubscriptions.Columns.AddRange(mntCmb, yearCmb, amount);
dgvSubscriptions.DataSource = _Data;
}
dgvSubscriptions.RowsDefaultCellStyle.Font = new Font("Trebuchet MS", 8F, FontStyle.Regular);
}
Instead of using this,use DataGridView
Try this:
With Calling GetCurrentRowValues method you can get selected row information's.
Complete Code
public Form1()
{
InitializeComponent();
dataGridView1.MultiSelect = false;
}
private void Form1_Load(object sender, EventArgs e)
{
List<string> Mon = new List<string>() { "January", "February", "March", "April", "May", " June", "July", "August", "September", "October", "November", "December" };
List<string> Year = new List<string>() { "2001", "2002", "2003", "2004", "2005", "2006" };
List<Data> _Data = new List<Data>();
for (int i = 1; i <= 12; i++)
{
_Data.Add(new Data() { Mon = Mon, Year = Year });
}
DataGridViewComboBoxColumn moonCmb = new DataGridViewComboBoxColumn();
moonCmb.HeaderText = "Month";
moonCmb.Name = "Month";
moonCmb.DataSource = Mon;
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
yearCmb.DataSource = Year;
DataGridViewTextBoxColumn amount = new DataGridViewTextBoxColumn();
amount.HeaderText = "Amount";
amount.Name = "Amount";
dataGridView1.Columns.AddRange(moonCmb, yearCmb, amount);
dataGridView1.DataSource = _Data;
}
private void GetCurrentRowValues()
{
var mon = dataGridView1.CurrentRow.Cells["Month"].Value;
var year = dataGridView1.CurrentRow.Cells["Year"].Value;
var amont = dataGridView1.CurrentRow.Cells["Amount"].Value;
}
}
public struct Data
{
public List<string> Mon { get; set; }
public List<string> Year { get; set; }
}
Result
New edit-From data table
#region Grid Column Names
dgvSubscriptions.AutoGenerateColumns = false;
dgvSubscriptions.ColumnCount = 1;
dgvSubscriptions.Columns[0].Name = "ID";
dgvSubscriptions.Rows.Clear();
DataGridViewComboBoxColumn mntCmb = new DataGridViewComboBoxColumn();
mntCmb.HeaderText = "Month";
mntCmb.Name = "Month";
//mntCmb.DataSource = dt;
mntCmb.DisplayMember = "paidformonth";
mntCmb.DataPropertyName = "paidformonth";
//mntCmb.ValueMember = "paidformonth";
mntCmb.DefaultCellStyle.NullValue = "";
mntCmb.ReadOnly = true;
mntCmb.Items.Add("april");
mntCmb.Items.Add("jun");
mntCmb.Items.Add("jull");
dgvSubscriptions.Columns.Add(mntCmb);
DataGridViewComboBoxColumn yearCmb = new DataGridViewComboBoxColumn();
yearCmb.HeaderText = "Year";
yearCmb.Name = "Year";
//yearCmb.DataSource = dt;
yearCmb.DisplayMember = "paidforyear";
//yearCmb.ValueMember = "paidforyear";
yearCmb.DataPropertyName = "paidforyear";
yearCmb.DefaultCellStyle.NullValue = "";
yearCmb.Items.Add("2001");
yearCmb.Items.Add("2002");
yearCmb.Items.Add("2003");
yearCmb.ReadOnly = true;
dgvSubscriptions.Columns.Add(yearCmb);
DataGridViewTextBoxColumn amount = new DataGridViewTextBoxColumn();
amount.HeaderText = "Subscription Amount";
amount.Name = "Subscription Amount";
amount.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
//amount.DataPropertyName = dt.Rows[i][2].ToString();
amount.DataPropertyName = "subamount";
amount.DefaultCellStyle.NullValue = "";
amount.ReadOnly = true;
dgvSubscriptions.Columns.Add(amount);
#endregion
Fill it
for (int i = 0; i < dt.Rows.Count; i++)
{
dgvSubscriptions.Rows.Add();
dgvSubscriptions.Rows[i].Cells[0].Value = dt.Rows[i][0].ToString();
dgvSubscriptions.Rows[i].Cells[1].Value = dt.Rows[i][1].ToString();
dgvSubscriptions.Rows[i].Cells[2].Value = dt.Rows[i][2].ToString();
dgvSubscriptions.Rows[i].Cells[3].Value = dt.Rows[i][0].ToString();
}
The forms ActiveControl property can help you.
var focusedCtrl = this.ActiveControl;
var siblings = Controls.Where(c => c.Location.Y == focusedCtrl.Location.Y).ToList();
foreach (Control c in siblings)
{
// all thise controls are on the same row, providede that the allign
}
Still I would sugget the DataGridView. It seems to be a better choise for a structure that looks like yours.
I’d go with the DataGridView but if you still want to keep this structure you might want to update KeyPressed event handler to look something like this
private string lastUsedTextBox = string.Empty;
private string lastEnteredValue = string.Empty;
private void txtJanAmt_KeyPress(object sender, KeyPressEventArgs e)
{
lastUsedTextBox = (sender as TextBox).Name;
lastEnteredValue = (sender as TextBox).Text;
}
And then when you press the save button you have everything stored here.
If you need to save all the data you can use dictionary or something like that.
I would like to do a plot with time function of data by using ultrachart , infragistics.
I have found this sample :
DataTable Recap = MarketData.Tables.Add("Recap");
// on ajoute des column a recap ne pas oublier de typer les colonnes
Recap.Columns.Add("Date", typeof(DateTime));
Recap.Columns.Add("Move Ticker price", typeof(double));
Recap.Columns.Add("Move Index price", typeof(double));
Recap.Columns.Add("Alpha",typeof (double));
// on remplie recap
for (int i = 0; i < TickerPrice.Rows.Count; i++)
{
DataRow destRow = Recap.NewRow();
destRow["Move Ticker price"] = TickerPrice.Rows[i]["CHG_PCT_1D"];
destRow["Move Index price"] = IndexPrice.Rows[i]["CHG_PCT_1D"];
destRow["Date"] = TickerPrice.Rows[i]["Date"];
Recap.Rows.Add(destRow);
}
// calcul du alpha
foreach (DataRow dr in Recap.Rows)
dr["Alpha"] = ((double)dr["Move Index price"]) * 1.5 - (double)dr["Move Ticker price"];
// remplir le feed alpha
FeedAlpha.DataSource = Recap;
// faire un plot
ChartPureAlpha.ChartType = Infragistics.UltraChart.Shared.Styles.ChartType.Composite;
ChartArea myChartArea = new ChartArea();
ChartPureAlpha.CompositeChart.ChartAreas.Add(myChartArea);
// Defines axes
AxisItem axisX = new AxisItem();
axisX.DataType = Infragistics.UltraChart.Shared.Styles.AxisDataType.Numeric;
axisX.Labels.ItemFormatString = "<DATA_VALUE:0.00>";
axisX.SetLabelAxisType = SetLabelAxisType.ContinuousData;
axisX.OrientationType = Infragistics.UltraChart.Shared.Styles.AxisNumber.X_Axis;
axisX.RangeType = AxisRangeType.Custom;
axisX.RangeMin = -1;
axisX.RangeMax = 1;
myChartArea.Axes.Add(axisX);
AxisItem axisY = new AxisItem();
axisY.DataType = Infragistics.UltraChart.Shared.Styles.AxisDataType.Numeric;
axisY.Labels.ItemFormatString = "<DATA_VALUE:0.00>";
axisY.Labels.HorizontalAlign = StringAlignment.Far;
axisY.SetLabelAxisType = SetLabelAxisType.ContinuousData;
axisY.OrientationType = Infragistics.UltraChart.Shared.Styles.AxisNumber.Y_Axis;
axisY.RangeType = AxisRangeType.Custom;
axisY.RangeMin = -1;
axisY.RangeMax = 1;
myChartArea.Axes.Add(axisY);
// Create and add series
XYSeries BPLseries = new XYSeries();
BPLseries.Label = "Blood L";
for (int i = 0; i < Recap.Rows.Count; i++)
BPLseries.Points.Add(new XYDataPoint((double)(Recap.Rows[i][2]), (double)Recap.Rows[i][1], "", false));
// Add a chartLayerAppearance
ChartLayerAppearance myScatterLayer = new ChartLayerAppearance();
myScatterLayer.ChartType = Infragistics.UltraChart.Shared.Styles.ChartType.ScatterChart;
myScatterLayer.ChartArea = myChartArea;
myScatterLayer.AxisX = axisX;
myScatterLayer.AxisY = axisY;
myScatterLayer.Series.Add(BPLseries);
ScatterChartAppearance sca1 = new ScatterChartAppearance();
sca1.ConnectWithLines = true;
sca1.Icon = SymbolIcon.None;
myScatterLayer.ChartTypeAppearance = sca1;
ChartPureAlpha.Series.Add(BPLseries);
ChartPureAlpha.CompositeChart.ChartLayers.Add(myScatterLayer);
CompositeLegend myLegend = new CompositeLegend();
myLegend.ChartLayers.Add(myScatterLayer);
myLegend.Bounds = new Rectangle(88, 2, 11, 15);
myLegend.BoundsMeasureType = MeasureType.Percentage;
myLegend.PE.ElementType = PaintElementType.Gradient;
myLegend.PE.FillGradientStyle = GradientStyle.ForwardDiagonal;
myLegend.PE.Fill = Color.CornflowerBlue;
myLegend.PE.FillStopColor = Color.Transparent;
myLegend.Border.CornerRadius = 10;
myLegend.Border.Thickness = 1;
ChartPureAlpha.CompositeChart.Legends.Add(myLegend);
It is working fine if I have data vs data but what I want is time (dd/mm/yyy) vs (double).
Please let me know if you have any idea.
Thanks
You can use the following code to get a time vs data chart:
using Infragistics.Win.UltraWinChart;
using Infragistics.UltraChart.Resources.Appearance;
DataTable dt = new DataTable();
dt.Columns.Add("Value", typeof(double));
dt.Columns.Add("Date", typeof(DateTime));
dt.Rows.Add(1.0, DateTime.Parse("04/20/2012"));
dt.Rows.Add(0.5, DateTime.Parse("04/21/2012"));
dt.Rows.Add(0.25, DateTime.Parse("04/22/2012"));
dt.Rows.Add(0.125, DateTime.Parse("04/23/2012"));
dt.Rows.Add(0.0625, DateTime.Parse("04/24/2012"));
dt.Rows.Add(0.03125, DateTime.Parse("04/25/2012"));
dt.Rows.Add(0.015625, DateTime.Parse("04/26/2012"));
dt.Rows.Add(0.0, DateTime.Parse("04/27/2012"));
NumericTimeSeries series = new NumericTimeSeries();
series.DataBind(dt, "Date", "Value");
UltraChart ultraChart = new UltraChart();
ultraChart.Data.SwapRowsAndColumns = true;
ultraChart.Dock = DockStyle.Fill;
ultraChart.ChartType = Infragistics.UltraChart.Shared.Styles.ChartType.LineChart;
ultraChart.DataSource = dt;
this.Controls.Add(ultraChart);