我正在试图找出UltraGrid Bands机制的奇怪行为。以下代码包含重新创建问题所需的一切。
我正在创建一个DataSet并用两个DataTable填充它。然后我将DataSet指定为BindingSource对象的DataSource。该BindingSource对象设置为UltraGrid.DataSource。
以下代码将有助于完全了解启动单个PrepareData()方法后发生的情况。网格显示3条记录,第一条记录可展开,以显示DataRelation引用的第二条带。您可以通过注释掉第二个电话来检查。
public partial class Form1 : Form {
BindingSource bs = new BindingSource();
DataSet ds = new DataSet();
public Form1() {
InitializeComponent();
DoLayout();
Bind();
PrepareData();
PrepareData();
}
private void DoLayout() {
ultraGrid1.DisplayLayout.Override.ExpansionIndicator = Infragistics.Win.UltraWinGrid.ShowExpansionIndicator.CheckOnDisplay;
}
private void Bind() {
bs.DataSource = ds;
ultraGrid1.DataSource = bs;
}
private void PrepareData() {
// you need to keep watching the ultraGrid1.DisplayLayout.Bands.All property
// all the time - normally it contains one entry,
// the default {NewDataSet} entry
bs.SuspendBinding();
ds.Relations.Clear();
ds.Clear();
ds.Tables.Clear();
// when the above code will run for the second time, you can see that
// Bands.All property will claim to have the standard {NewDataSet} entry
// again. Seems like everything is working well
DataTable dt = new DataTable("TABLE1");
dt.Columns.Add("col1");
dt.Columns.Add("col2");
dt.Columns.Add("col3");
dt.Rows.Add("1", "1", "1");
dt.Rows.Add("2", "2", "2");
dt.Rows.Add("3", "3", "3");
// after adding the datatable to the dataset, we can see that there was
// a change made to the DisplayLayout.Band.All list of the ultraGrid1
// {NewDataSet} will change to {TABLE1}
//
// now watch the behavior when the method is run for the second time
ds.Tables.Add(dt);
// after the second run, you can see the first problem in the Bands.All entries
dt = new DataTable("TABLE2");
dt.Columns.Add("scol1");
dt.Columns.Add("scol2");
dt.Rows.Add("s1", "1");
dt.Rows.Add("s2", "1");
dt.Rows.Add("s3", "1");
// the Bands.All property still will say there is only one element in it
// but not anymore once the code is executed for the second time
ds.Tables.Add(dt); // for the second code run - here is the second problem
// now the first time we add that relation, you can see that
// a new entry exists in the Bands.All property of the ultraGrid1: {T1T2}
dt.ParentRelations.Add("T1T2", ds.Tables["TABLE1"].Columns["col1"], dt.Columns["scol2"], false);
// after the second run of the code, here you can see the third problem
bs.ResumeBinding();
}
}
现在,如果再次运行PrepareData()方法,网格会变得混乱。我实际上发现了导致问题的原因,因此上面代码中的重要评论,但我无法弄清楚为什么会发生这种情况。因此,无论方法被调用多少次,我都希望网格的行为完全相同。
有没有人知道这可能是什么原因?
我已经尝试使DataSources为空,并重新分配它们;累了改变所谓方法的顺序;甚至试图调用BandsCollection对象的非公共方法,如“ClearAllButBandZero”和“Clear”,但这一切都无济于事。
我在Infragistics DevCenter的知识库中找到了一个技巧: http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.Aspx?ArticleID=1751 但这对我的情况没有帮助。每次重构DataSet时,UltraGrid.DisplayLayout.Bands集合都变得越来越混乱。
答案 0 :(得分:1)
没有必要使用BindingSource在UltraGrid中添加数据集作为数据源。您可以将数据集直接指定为网格的数据源。请查看以下代码:
public partial class Form1 : Form
{
DataSet ds = new DataSet();
public Form1()
{
InitializeComponent();
DoLayout();
PrepareData();
PrepareData();
}
private void DoLayout()
{
ultraGrid1.DisplayLayout.Override.ExpansionIndicator = Infragistics.Win.UltraWinGrid.ShowExpansionIndicator.CheckOnDisplay;
}
private void Bind()
{
ultraGrid1.DataSource = ds;
}
private void PrepareData()
{
ds = null;
ds = new DataSet();
DataTable dt = new DataTable("TABLE1");
dt.Columns.Add("col1");
dt.Columns.Add("col2");
dt.Columns.Add("col3");
dt.Rows.Add("1", "1", "1");
dt.Rows.Add("2", "2", "2");
dt.Rows.Add("3", "3", "3");
ds.Tables.Add(dt);
dt = new DataTable("TABLE2");
dt.Columns.Add("scol1");
dt.Columns.Add("scol2");
dt.Rows.Add("s1", "1");
dt.Rows.Add("s2", "1");
dt.Rows.Add("s3", "1");
ds.Tables.Add(dt);
dt.ParentRelations.Add("T1T2", ds.Tables["TABLE1"].Columns["col1"], dt.Columns["scol2"], false);
Bind();
}
}
答案 1 :(得分:1)
我发现了导致这种行为的原因。这是.NET Framework中的一个错误。 BindingSource类上有一个私有字段:
private Dictionary<string, BindingSource> relatedBindingSources;
问题是,一旦为BindingSource.DataSource分配null,字典仍保持不变。然后分配新的DataSource,在其中添加关系,Dictionary增长。永远都不会停止。
我解决这个问题的方法是创建一个简单的方法,以确保删除所有可能的关系:
private void ClearRelatedBindingSources(BindingSource bindingSource) {
System.Reflection.FieldInfo fi = bindingSource.GetType().GetField("relatedBindingSources", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
Dictionary<string, BindingSource> relatedBsDict = fi.GetValue(bindingSource) as Dictionary<string, BindingSource>;
if (relatedBsDict != null) {
relatedBsDict.Clear();
}
}
所有要做的就是在使BindingSource.DataSource属性归零后调用该方法。这基本上解决了网格中带复制的问题。
非常感谢Thanasis,感谢我开始在正确的地方挖掘;)