Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting selected value of dynamic textboxes and comboboxes

Tags:

c#

winforms

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 enter image description here

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

  1. How do I set the value of the comboboxes as selected when I get it from the datatable
  2. For the textbox how do I get the value from the datatable
  3. 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.

enter image description here

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);

}
like image 501
Adrian Avatar asked Oct 05 '22 09:10

Adrian


1 Answers

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

enter image description here

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();
        }
like image 148
KF2 Avatar answered Oct 13 '22 11:10

KF2