Frage

I'm working my brain off trying to figure out a strange behavior of the UltraGrid Bands mechanism. The below code contains everything you need to re-create the problem.

I'm creating a DataSet and filling it with two DataTables. Then I assign the DataSet as a DataSource of BindingSource object. That BindingSource object is set as an UltraGrid.DataSource.

The below code will be helpful to fully understand what's going on after a single PrepareData() method is launched. The grid displays 3 records with the first one expandable to show the second Band referenced to it by DataRelation. You can check that by commenting out the second call.

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

}

Now if you run the PrepareData() method once more, the grid gets messy. I actually found what's causing the problem, thus the heavy comments in the code above, but I can't figure out why is this happening. As a result I simply want the grid to behave exactly the same no matter how many times the method is called.

Does anyone have a clue what could be the reason for this?

I already tried to null the DataSources, and re-assigning them; tired changing the order of the methods called; even tried to invoke non-public methods of the BandsCollection object like "ClearAllButBandZero" and "Clear", but it was all to no avail.

I've found an artible in the KnowledgeBase of the Infragistics DevCenter: http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.Aspx?ArticleID=1751 but that didn't help in my case. Each time the DataSet is reconstructed, the UltraGrid.DisplayLayout.Bands collection is getting more and more messy.

War es hilfreich?

Lösung 2

I've found what's causing such behaviour. It's a bug in the .NET Framework. There is a private field on the BindingSource class:

private Dictionary<string, BindingSource> relatedBindingSources;

The problem is that once you assign null to your BindingSource.DataSource, the Dictionary remains untouched. Then you assign new DataSource, add a relation in it, the Dictionary grows. And never stops.

My solution to this problem was creating a simple method, that will assure me that all possible relations are removed:

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

All there is to do is to call that method after nulling the BindingSource.DataSource property. That essentially solved the problem of band replication in my grids.

Many thanks to Thanasis thanks to whom I began to dig in the right place ;)

Andere Tipps

It is not necessary to use BindingSource to add a dataset as a datasource in UltraGrid. You can assign the dataset directly as grid's datasource. Take a look to the following code:

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

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top