我想做以下事情,但不能完全实现目标。我在表单上有一个datagridview,我想在每次单击按钮时将源设置为不同的数据表。
DynamicsTableAccess ta;
private void button1_Click(object sender, EventArgs e)
{
//the DataSource for both calls will be a DataTable
//first button click
this.dataGridView1.DataSource = ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3});
//second button click
this.dataGridView1.DataSource = ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 });
//etc
}
我想我需要使用某种类型的集合来保存我的每个数据库调用,例如:
Foo.Add(ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3}));
Foo.Add(ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 }));
然后点击每个按钮迭代该集合:
int index = 0;
private void button1_Click(object sender, EventArgs e)
{
this.dataGridView1.DataSource = Foo[index];
index++;
}
我意识到这可能需要某种代表,如果有可能的话,我通常可以绕过它们,但不是这次。
我意识到这绝不应该在生产代码中结束,我只是用它来测试我的数据库调用,并且一旦完成就会埋葬它。我对完全不同的方法提出了建议,但主要是在寻找如何构建Foo以实现这一特定目标。
答案 0 :(得分:1)
我假设ta.GetLineItemsByCustomerAndDate
和ta.GetLineItemsByDocumentRange
都返回DataTable
;如果没有,只需用适当的类型替换下面的任何DataTable
次出现。
您的代码的问题在于您在将所述方法添加到列表之前执行所述方法,从而有效地仅将其结果存储在列表中。相反,您需要在以后存储其执行的封装。要实现后者,如您所建议的那样,您需要使用委托。在C#3.5中,通过引入lambda expressions,明显简化了声明委托所需的语法;我建议你阅读它们。
因此,我们首先声明您的Foo
列表(可能是一个类实例变量)来保存我们希望稍后执行的委托(或函数)。
List<Func<DataSet>> Foo = new List<Func<DataTable>>();
然后,我们可以将我们的方法调用(封装为匿名函数)添加到列表中。请注意,() =>
语法会导致任何成功的语句被封装为匿名函数。
Foo.Add(() => ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3}));
Foo.Add(() => ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 }));
最后,我们只需要引用列表中的一个委托 - Foo[index]
- 并通过追加通常与方法调用关联的()
来调用它。
int index = 0;
private void button1_Click(object sender, EventArgs e)
{
dt.Clear();
this.dataGridView1.DataSource = Foo[index]();
index++;
}
编辑:您尝试的内容会给您这样的内容:
List<Func<object[], DataTable>> Foo = new List<Func<object[], DataTable>>();
Foo.Add((objs) => ta.GetLineItemsByCustomerAndDate(objs));
Foo.Add((objs) => ta.GetLineItemsByDocumentRange(objs));
...或者,更简洁地使用集合初始化器:
var Foo = new List<Func<object[], DataTable>>()
{
(objs) => ta.GetLineItemsByCustomerAndDate(objs),
(objs) => ta.GetLineItemsByDocumentRange(objs),
};
...或者,更简洁:
var Foo = new List<Func<object[], DataTable>>()
{
ta.GetLineItemsByCustomerAndDate,
ta.GetLineItemsByDocumentRange,
};
但是,您需要为每个匿名函数提供相应的参数,以便调用它。
this.dataGridView1.DataSource = Foo[0](new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3});
this.dataGridView1.DataSource = Foo[1](new object[] { "01254785", "01254885", 3 });
在这种情况下,这样做是不可取的,因为您试图将整个方法调用(包括给定的参数)封装为匿名函数的一部分。您可以告诉原始匿名函数更“完整”,因为它的类型为Func<DataTable>
,这意味着它的返回类型为DataTable
但不接受任何参数。
答案 1 :(得分:1)
您假设您的GetLineItemsByDocumentRange
方法定义如下:
public DataTable GetLineItemsByDocumentRange(object[] filter)
{
}
定义像这样的过滤器:
List<Func<DataTable>> filters = new List<Func<DataTable>>();
filters.Add(() => ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3}));
filters.Add(() => ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 }));
每次致电
this.dataGridView1.DataSource = filters[index]();
将重新评估过滤器,返回当前客户。