1

我正在努力找出 UltraGrid Bands 机制的奇怪行为。以下代码包含重新创建问题所需的一切。

我正在创建一个数据集并用两个数据表填充它。然后我将 DataSet 分配为 BindingSource 对象的 DataSource。该 BindingSource 对象设置为 UltraGrid.DataSource。

下面的代码将有助于完全理解启动单个 PrepareData() 方法后发生的情况。网格显示 3 个记录,第一个可展开以显示 DataRelation 引用的第二个 Band。您可以通过注释掉第二个电话来检查。

    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() 方法,网格就会变得混乱。我实际上找到了导致问题的原因,因此上面代码中的大量注释,但我无法弄清楚为什么会发生这种情况。因此,无论调用多少次方法,我都希望网格的行为完全相同。

有谁知道这可能是什么原因?

我已经尝试清空数据源,并重新分配它们;厌倦了改变调用方法的顺序;甚至尝试调用 BandsCollection 对象的非公共方法,如“ClearAllButBandZero”和“Clear”,但都无济于事。

我在 Infragistics DevCenter 的知识库中找到了一篇文章: http ://devcenter.infragistics.com/Support/KnowledgeBaseArticle.Aspx?ArticleID=1751 但这对我没有帮助。每次重新构建 DataSet 时,UltraGrid.DisplayLayout.Bands 集合都会变得越来越乱。

4

2 回答 2

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();
    }

}
于 2012-12-12T22:50:15.517 回答
1

我找到了导致这种行为的原因。这是 .NET Framework 中的一个错误。BindingSource 类上有一个私有字段:

private Dictionary<string, BindingSource> relatedBindingSources;

问题是,一旦您将 null 分配给您的 BindingSource.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 属性设为空后调用该方法。这基本上解决了我的网格中波段复制的问题。

非常感谢萨纳西斯,感谢我在正确的地方开始挖掘;)

于 2012-12-13T16:18:17.287 回答