Infragistics UltraGrid(9.2)重新创建数据源后重复绑定

时间:2012-12-12 21:48:11

标签: winforms dataset infragistics duplication ultragrid

我正在试图找出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集合都变得越来越混乱。

2 个答案:

答案 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,感谢我开始在正确的地方挖掘;)