我有一个问题,我已经研究了几天了,我只是想不出一个合乎逻辑的方式来做我想做的事。
我有一个有任务列表的应用程序。它从3个控件开始:一个文本框,一个datetimepicker和一个PictureBox,它可以在点击时更改图像。然后,用户可以按下将在下面添加另一行控件的图像(它从已创建的控件中获取动态控件的属性):
https://www.dropbox.com/s/o2pub6orww24w25/tasklist.png(这是一个更清晰的屏幕截图)
现在我要做的是将每个行(一行被定义为:Textbox,Date,Status)的值保存到SQLite DB中。
第一行很容易,因为它有一个独特的设计名称(并且是一个'静态'控件)。 但是,当我尝试从动态控件中保存值时问题就出现了:
问题a)我无法引用动态控件,因为“它在当前上下文中不存在”。 - 创建控件的函数有一个公共访问修饰符,所以我认为应该这样做? - 没有。我也尝试过:Panel1.pb.blah
但它仍然无法识别控件?
问题b)如何告诉我的程序每行是一组新数据?换句话说,如何为每一行运行一个新的插入命令? - 我想把它作为一个for-each-textbox循环,但是不是每次都拿起第一个动态日期吗?
我还想过使用tag属性并将其设置为counter变量,以对行中的控件进行分组。 (计数器是一个整数,每次添加新行时都会递增。)但是我不能这样做,因为图片框使用标签属性作为其功能的一部分来更改点击图像(多次更改)。
代码:
添加控件:
public void pictureBox1_Click(object sender, EventArgs e)
{
//TextBox Control
int tbh = tasktb.Location.Y + (counter*25);
int tbsh = tasktb.Size.Height;
int tbsw = tasktb.Size.Width;
TextBox tb = new TextBox();
tb.Location = new Point(9, tbh);
tb.Size = new System.Drawing.Size(tbsw, tbsh);
tb.Tag = counter.ToString();
//Date Time Control
int dth = duedatedb.Location.Y + (counter * 25);
int dtsh = duedatedb.Size.Height;
int dtsw = duedatedb.Size.Width;
DateTimePicker dtp = new DateTimePicker();
dtp.Location = new Point(300, dth);
dtp.Size = new Size(dtsw, dtsh);
dtp.Format = System.Windows.Forms.DateTimePickerFormat.Short;
//Picture Box Control
int stsh = status.Location.Y + (counter * 25);
int stssh = status.Size.Height;
int stssw = status.Size.Width;
PictureBox pb = new PictureBox();
pb.Location = new Point(429, stsh);
pb.Size = new Size(stssw, stssh);
pb.Image = Red;
pb.Click += new System.EventHandler(pb_Click);
panel1.Controls.Add(tb);
panel1.Controls.Add(dtp);
panel1.Controls.Add(pb);
++counter;
}
尝试引用控件:(为了在单击时更改图像)[在MSDN网站上查找Control.Find函数]
public void pb_Click(object sender, EventArgs e)
{
PictureBox pb = (panel1.Controls.Find("pb",false));
if (pb.Image == Red) { pb.Image = Orange; status.Tag = "Orange"; }
else if (pb.Image == Orange) { pb.Image = green; status.Tag = "Green"; }
else if (pb.Image == green) { pb.Image = Red; status.Tag = "Red"; }
}
这里的基本问题是问题a,如果你们可以看到我在哪里出错了,我就可以离开并尝试编写一些代码来解决问题b。 (我已经将问题b包括在内,以获得有关最佳方法的建议。 - 目前我一无所知!)
感谢您的任何帮助!真的很感激!
答案 0 :(得分:2)
ControlCollection.Find
查找具有指定名称的控件,但您尚未设置任何控件。代码中的变量名称并不相关。所以,要么:
pb.Name = "pb";
但这意味着你最终会有几个同名的物品。因此,看看你想如何改变点击的PictureBox的图片,只需这样做:
public void pb_Click(object sender, EventArgs e)
{
PictureBox pb = (PictureBox)sender;
if (pb.Image == Red) { pb.Image = Orange; status.Tag = "Orange"; }
else if (pb.Image == Orange) { pb.Image = green; status.Tag = "Green"; }
else if (pb.Image == green) { pb.Image = Red; status.Tag = "Red"; }
}
sender
参数始终包含对引发事件的控件的引用,在这种情况下,无论哪个图片框都被点击了!
编辑:至于你的另一个问题,我假设你以后需要对控件进行操作,所以我建议你存储对所有控件的引用(或者至少是你需要的引用),像这样:
// helper class
private class Entry
{
public TextBox TextBox { get; private set; }
public DateTimePicker DateTimePicker { get; private set; }
public PictureBox PictureBox { get; private set; }
public Entry( TextBox tb, DateTimePicker dtp, PictureBox pb )
{
this.TextBox = tb;
this.DateTimePicker = dtp;
this.PictureBox = pb;
}
}
// member field
private List<Entry> m_Entries = new List<Entry>();
// at the end of pictureBox1_Click
public void pictureBox1_Click(object sender, EventArgs e)
{
....
m_Entries.Add( new Entry( tb, dtp, pb ) );
}
然后,您可以使用该列表中的项目与您的行进行交互。您可能还想添加索引或对原始数据结构的引用。另外,您可能想要考虑是否真的要自己创建控件,或者实际使用某种表/网格控件来托管它们!
或者只是在一个UserControl
中包含所有这些控件,包含逻辑和所有控件!