【问题标题】:C# accessing a datatable constructed at runtime from anywhere elseC# 从其他任何地方访问在运行时构建的数据表
【发布时间】:2019-03-19 21:45:21
【问题描述】:

所以我有以下代码:

public partial class Buttons : Form
{
    private DataSet AllEventData = new DataSet("AllEventData");
    private DataTable makeButtonsTable()
    {
        DataTable buttonData = AllEventData.Tables.Add("ButtonData");
        DataColumn column1, column2, column3;

        column1 = new DataColumn();
        column1.DataType = Type.GetType("System.Int32");
        column1.ColumnName = "ID";
        column1.AutoIncrement = true;
        column1.AutoIncrementSeed = 1;
        column1.AutoIncrementStep = 1;

        buttonData.Columns.Add(column1);

        column2 = new DataColumn("Button Name", typeof(String));
        buttonData.Columns.Add(column2);

        column3 = new DataColumn("Button Location", typeof(Rectangle));
        buttonData.Columns.Add(column3);

        buttonData.PrimaryKey = new DataColumn[] { column1 };

        return buttonData;
    }

    public Buttons()
    {
        InitializeComponent();
        DataTable buttonData = makeButtonsTable();
        buttonGridView.DataSource = buttonData;
        buttonGridView.Columns["ID"].Visible = false;  
    }

    private void LaunchScreenSelection_Click(object sender, EventArgs e)
    {
        ss = new ScreenSelection(buttonData);
        ss.Show(this);
    }
}

我的最终目标是让在 ScreenSelection 表单中输入的信息将数据添加到 datagridview,我认为这意味着将其添加到数据表中,但我不清楚。

当我尝试从 LaunchScreenSelection_Click 访问 buttonData 时,它当然会告诉我 buttonData 在当前上下文中不存在。哪个,是的,我有点明白......但考虑到我在这里构建的一切,我不知道如何让它在当前环境中存在。我尝试过的所有尝试都会产生更多错误(我很乐意在此处列出所有尝试,但是……这会变得很长)。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# datagridview datatable dataset


    【解决方案1】:

    处理这种情况的正确方法是通过自定义事件。

    让我们开始定义一个类,我们将使用它在 ScreenLocation 表单和 Buttons 表单之间传输信息。这个类应该是公共的,并且对两个表单类(相同的命名空间)都是可见的,它可以在自己的文件中,也可以只是附加到 ScreenLocation/Buttons 表单中

    public class ButtonData
    { 
        public int ID { get; set; }
        public string Name { get; set; }
        public Rectangle Rect { get; set; }
    }
    

    现在我们将添加定义由 ScreenLocation 表单引发的事件所需的样板代码

    public class ScreenSelection : Form
    {
         public delegate void onDataReady(ButtonData data);
         public event onDataReady DataReady;
         ....
    }
    

    此时我们可以更改 ScreenLocation 类,添加在数据准备好传输给任何监听事件的人时引发事件的代码。
    例如,ScreenLocation 中的 ButtonClick 处理程序可以这样编写

    protected void ButtonSave_Click(object sender, EventArgs e)
    {
         // Anyone has subscribed to the event?
         if(DataReady != null)
         {
             ButtonData btn = new ButtonData();
    
             // Change these GetXXXXValue with the appropriate code 
             // that extracts the info from the ScreenLocation UI.
             btn.ID = GetTheIDValue();
             btn.Name = GetTheNameValue();
             btn.Rect = GetTheRectValue();
    
             // Send the info to the interested parties.
             DataReady(btn);
         }
    }
    

    当您在 Buttons 表单中的代码中创建 ScreenLocation 的实例时,圆圈是闭合的。

    private void LaunchScreenSelection_Click(object sender, EventArgs e)
    {
        ss = new ScreenSelection(buttonData);
    
        // Tell the ScreenLocation ss instance that we are 
        // interested to know when new data is ready
        ss.DataReady += myDataLoader;
        ss.Show(this);
    }
    
    // When the *ScreenLocation* instance will raise the event, 
    // we will be called here to handle the event
    private void myDataLoader(ButtonData btn)
    {
         // Now you have your info from the ScreenLocation instance 
         // and you can add it to the datatable used as datasource for the grid 
         DataTable dt = AllEventData.Tables["AllEventData"];
         dt.Rows.Add(btn.ID, btn.Name, btn.Rect);
    }
    

    【讨论】:

    • 所以我在尝试这个时遇到了一些问题: 1,传递给 ss = new ScreenSelection 的“buttonData”仍然无法访问。我也许可以通过使用 AllEventData.Tables["ButtonData"] 调用来解决这个问题(我认为,这就是你在 DataTable dt = etc 中的意思) 2. 我似乎需要两种形式的 ButtonData 类,因为我会从 myDataLoader 和表单 init 调用它并单击? 3. 自动计数器的 ID 必须为空。尽管如此,当我尝试它时, += myDataLoader 行说没有重载匹配委托。也许这与#2有关?
    • 啊,我不得不单独添加一个公共类,这样两者都可以访问。亲爱的,这行得通,谢谢!
    【解决方案2】:

    如果我理解正确,变量 buttonData 仅存在于您的 makeButtonsTable() 函数中。但是,您确实有全局变量 AllEventData,它引用了“ButtonData”表,因为您在此处添加了它。

       DataTable buttonData = AllEventData.Tables.Add("ButtonData");
    

    因此,您只需从 AllEventData 发送该表作为 ScreenSelection 的参数。

       private void LaunchScreenSelection_Click(object sender, EventArgs e)
       {
         ss = new ScreenSelection(AllEventData.Tables["ButtonData"]);
         ss.Show(this);
       }  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多