2013-04-15 89 views
5

我在c#中有一个winform,我动态地创建了两个组合框和一个文本框。当用户选择说月份和年份并在文本框中输入一个值时,我希望在单击按钮时保存相关的组合框值。默认情况下,月份和年份组合框将选择当前的月份和年份。获取动态文本框和组合框的选定值

在同一屏幕中还有另一部分数据将填充上个月,例如组合框和文本框中的当前年份从1月到3月(如果可用)。

我不确定这种方法是否正确,或者我应该使用datagridview。下面是截图和我的代码。有关我如何做到这一点的任何建议。

截图 enter image description here

代码

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

编辑1

我用下面的代码从数据表,但无法获取数据做如下

  1. 我如何设置组合框的值,每当有可用的数据我想该行是作为选择的,当我从数据表
  2. 对TextBox得到它如何从DataTable中
  3. 获得的价值只读。

在此先感谢

更改代码

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

编辑2

我似乎是困惑,为什么我越来越有6列3行。该数据表只有2行和3列。我正在使用上面的代码。我添加了ID列以查看会发生什么。请参阅下面的截图。我有

dgvSubscriptions.AllowUserToAddRows = true 

因为我希望用户添加行并输​​入更多的数据进行保存。我在这里想要做的是获得支付月份/年的订阅列表,并允许用户添加订阅,例如假设1月到4月支付6月5月。

enter image description here

编辑3

我甚至设置DataPropertyName而不是ValueMember依然没有改变

编辑代码

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

编辑4

下面是导致重复列

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 

} 

编辑5

我用IRSOG代码进行一些修改和下面是完整的工作代码的实际代码。

工作守则

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

您可以简单地把控制C作为文本框,并检查它是否不为空,那么得到的文本框 –

+1

文本有您使用[DataGridView中(http://msdn.microsoft.com/en-us考虑/library/system.windows.forms.datagridview.aspx)取而代之? –

+0

@RajeevKumar我能做到这一点,但如果你再看到我的截图我想在文本框 – Adrian

回答

2

而不是使用这个的,使用DataGridView 试试这个:

随着调用即可获得选定行信息的GetCurrentRowValues方法。

完整代码

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

结果

enter image description here

新编辑从数据表

 #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 

填充它

 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

嗯...我开始像这样,半途而废:)。让我试一下你的代码并看看。只有一个问题 - 我的列表字符串年可想有过去5年加上当前和明年 – Adrian

+0

你的代码的工作只需要找出如何从金额列 – Adrian

+0

@Adrian输入数字和小数点限制用户:第一个问题是不难实现,且秒的问题:你必须创建自定义的dataGridView的列,其中地方你想要的任何控制:HTTP://msdn.microsoft.com/en-us/library/7tas5c80.aspx – KF2

1

的形式ActiveControl属性可以帮助你。

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 
} 

我仍然会建议DataGridView。对于一个看起来像你的结构,它似乎是一个更好的选择。

+0

感谢让我看看我是否可以使用datagridview。我尝试使用DataGridView时遇到的问题是如何动态地填充组合框列。我会尝试看看 – Adrian

+0

@Adrian我[见](http://stackoverflow.com/questions/7648648/dynamic-combobox-in-a-datagridview)你的问题。也许你需要更好的GridView。我总是使用[XtraGrid](http://www.devexpress.com/Products/NET/Controls/WinForms/Grid/),但它不是免费的。 –

1

我会去与DataGridView的,但如果你仍然想保持这种结构你可能要更新keyPressed事件处理程序看起来像这样

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

而且那么当你按下保存按钮时,你已经存储了所有的东西。

如果您需要保存所有数据,您可以使用字典或类似的东西。

+0

谢谢我已经去了datagridview,但仍然有一些问题检查我编辑的问题。不知道如何设置组合框的DataTable中的值 – Adrian