引用和存储来自动态创建控件的数据

本文关键字:创建 控件 数据 动态 存储 引用 | 更新日期: 2023-09-27 18:13:28

我有一个问题,我已经研究了几天了,我就是想不出一个合乎逻辑的方法来做我想做的事情。

我有一个应用程序,其中有一个任务列表。它开始有3个控件:一个文本框,日期时间选择器和一个图片框改变图像点击。然后,用户可以按下一个图像,它将在下面添加另一行控件(它从已经创建的控件中获取动态控件的属性):

https://www.dropbox.com/s/o2pub6orww24w25/tasklist.png(这是一个截图,使它更清楚)

现在我想做的是保存值从每一行(一行被定义为:文本框,日期,状态)到SQLite数据库。

第一行很简单,因为它有一个独特的设计名称(并且是一个"静态"控件)。但是,当我试图保存动态控件中的值时,问题就出现了:

问题a)我无法引用动态控件,因为'它不存在于当前上下文中'。-用于创建控件的功能有一个公共访问修饰符,所以我认为应该做的技巧?——没有。我也试过:Panel1.pb.blah,但它仍然没有识别控制?

问题b)我如何告诉我的程序,每一行是一个新的数据集?换句话说,我如何为每一行运行一个新的插入命令?-我认为这样做作为一个for-each-textbox循环,然而,不只是拿起第一个动态日期每次?

我还想到使用标签属性并将其设置为计数器变量,以便对行中的控件进行分组。(计数器是一个整数,每次添加新行都会增加。)但是我不能这样做,因为图片框使用tag属性作为其功能的一部分,可以在单击时更改图像(更改多次)。

代码:

添加控件:

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网站上查找此功能]

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包含在这里,是为了得到你的建议。-目前我没有线索!)

感谢您的帮助!真的很感激!

引用和存储来自动态创建控件的数据

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中,包括逻辑和所有!