我在c#中有一个winform,我动态创建了两个组合框和一个文本框。当用户选择说出月份和年份并在文本框中输入值时,我想在单击按钮保存时获取相关的组合框值。默认情况下,月份和年份组合框将选择当前月份和年份。
在同一个屏幕中还有另一个部分,其中数据将在前一个月填充,例如今年1月到3月的组合框和文本框(如果有的话)。
我不确定这种方法是否正确,或者我应该使用datagridview。下面是截图和我的代码。关于我如何做到这一点的任何建议。
截图
代码
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
我使用下面的代码从数据表中获取数据,但无法执行以下操作
提前致谢
更改了代码
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
我似乎很困惑为什么我得到3行6列。数据表只有2行3列。我正在使用上面的代码。我添加了ID列,看看会发生什么。请参见下面的截图。我有
dgvSubscriptions.AllowUserToAddRows = true
因为我希望用户添加行并输入更多数据进行保存。我在这里要做的是获得已支付的月份/年份的订阅列表,并允许用户添加订阅,例如5月,6月,假设1月到4月已经支付。
编辑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 :(得分: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; }
}
<强>结果强>
新编辑 - 来自数据表
#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();
}
答案 1 :(得分: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。对于看起来像你的结构来说,这似乎是一个更好的选择。
答案 2 :(得分: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;
}
然后当您按下保存按钮时,您将所有内容存储在此处。
如果您需要保存所有数据,可以使用字典或类似的东西。