2013-04-15 14 views
5

Ho una forma win in C# che ho creato dinamicamente due caselle combinate e una casella di testo. Quando un utente seleziona dire il mese e l'anno e inserisce un valore nella casella di testo, voglio ottenere i relativi valori delle caselle combinate quando si fa clic sul pulsante per salvare. Per impostazione predefinita, nella casella combinata mese e anno verranno selezionati il ​​mese e l'anno corrente.Ottenere il valore selezionato di caselle di testo dinamiche e caselle combinate

C'è anche un'altra parte nella stessa schermata in cui i dati verranno compilati per il mese precedente come da gennaio a marzo per l'anno corrente nelle caselle combinate e le caselle di testo, se disponibili.

Non sono sicuro se questo approccio sia corretto o dovrei andare con un datagridview. Di seguito è lo screenshot e il mio codice. Qualche suggerimento su come posso farlo.

Schermata enter image description here

Codice

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

ho usato il codice qui sotto, che riceve i dati dal DataTable, ma non in grado di effettuare le seguenti operazioni

  1. Come faccio a impostare il valore delle caselle combinate come selezionato quando ho capito dal datatable
  2. Per la casella di testo come faccio ad ottenere il valore dal datatable
  3. Ogni volta che ci sono dati disponibili voglio che fila per essere sola lettura.

Grazie in anticipo

codice modificato

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

mi sembra di essere confuso sul motivo per cui io sono sempre 3 righe con 6 colonne. Il datatable ha solo 2 righe e 3 colonne. Sto usando il codice sopra. Ho aggiunto la colonna ID solo per vedere cosa succede. Guarda lo screenshot qui sotto. Ho

dgvSubscriptions.AllowUserToAddRows = true 

come voglio che l'utente aggiunga righe e inserisca più dati da salvare. Quello che sto cercando di fare qui è quello di ottenere una lista di abbonamento di mesi/anni che sono stati pagati e consentire agli utenti di aggiungere l'abbonamento per dire maggio, giugno supponendo che Jan e April siano stati pagati.

enter image description here

Edit 3

Ho anche impostato il DataPropertyName al posto del ValueMember ancora nessun cambiamento

cura Codice

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

seguito è il codice effettivo che causa le colonne duplicate

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

Ho usato codice IRSOG con alcune modifiche e sotto è il codice di lavoro completa.

codice di lavoro

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

} 
+0

È possibile trasmettere il controllo c come TextBox e controllare se non è null, quindi ottenere il testo dalla casella di testo –

+1

Hai considerato l'utilizzo di un [DataGridView] (http://msdn.microsoft.com/en-us /library/system.windows.forms.datagridview.aspx) Invece? –

+0

@RajeevKumar sono stato in grado di farlo, ma ancora una volta, se si vede la mia screenshot voglio le comboboxes valore per il valore immesso nelle caselle di testo – Adrian

risposta

2

Invece di usare questo, utilizzare DataGridView Prova questo:

con chiamate GetCurrentRowValues metodo è possibile ottenere informazioni selezionate fila di.

codice completo

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

Risultato

enter image description here

Nuovo edit-Dalla tabella dei dati

 #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 

riempirlo

 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(); 
     } 
+0

Hmm ... Ho iniziato così e mi sono perso a metà strada :). Lasciami provare con il tuo codice e vedere. Solo una domanda - L'Anno lista di stringhe posso desiderare di avere negli ultimi 5 anni oltre l'anno in corso e il prossimo – Adrian

+0

vostri codici funziona solo bisogno di trovare il modo di impedire all'utente di inserire numeri e punti decimali nella colonna Importo – Adrian

+0

@Adrian : la prima domanda non è difficile da implementare e la domanda sec: è necessario creare una colonna di DataGridView personalizzata dove posizionare qualsiasi controllo desiderato: http: //msdn.microsoft.com/en-us/library/7tas5c80.aspx – KF2

1

Le forme ActiveControl proprietà può aiutare.

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 
} 

Ancora vorrei sugget il DataGridView. Sembra essere una scelta migliore per una struttura che assomiglia al tuo.

+0

Grazie fammi vedere se riesco a farlo funzionare con il datagridview. Il mio problema che ho avuto quando ho provato con DataGridView è stato come compilare la colonna combo in modo dinamico. Proverò a vedere – Adrian

+0

@Adrian I [vedi] (http://stackoverflow.com/questions/7648648/dynamic-combobox-in-a-datagridview) il tuo problema. Forse hai bisogno di un GridView migliore. Io uso sempre [XtraGrid] (http://www.devexpress.com/Products/NET/Controls/WinForms/Grid/) ma non è gratuito. –

1

mi piacerebbe andare con la DataGridView, ma se si vuole ancora mantenere tale struttura si potrebbe desiderare di aggiornare gestore di eventi keyPressed a guardare qualcosa di simile

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

E quindi quando si preme il pulsante Salva, tutto è memorizzato qui.

Se è necessario salvare tutti i dati è possibile utilizzare un dizionario o qualcosa del genere.

+0

Grazie che sono andato con il datagridview ma ancora qualche problema controlla la mia domanda modificata. Non sei sicuro di come impostare i valori dal DataTable delle combobox – Adrian

Problemi correlati