Infragistics UltraGrid (9.2) Дублирование полосы после воссоздания источника данных

Я стараюсь изо всех сил пытаться выяснить странное поведение механизма UltraGrid Bands. Приведенный ниже код содержит все необходимое для воссоздания проблемы.

Я создаю DataSet и заполняю его двумя DataTables. Затем я назначаю DataSet как DataSource объекта BindingSource. Этот объект 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(), сетка станет грязной. На самом деле я обнаружил, что является причиной проблемы, таким образом, тяжелые комментарии в коде выше, но я не могу понять, почему это происходит. В результате я просто хочу, чтобы таблица работала одинаково независимо от того, сколько раз вызывается метод.

Кто-нибудь знает, что может быть причиной этого?

Я уже пытался обнулить источники данных и переназначить их; надоело менять порядок вызываемых методов; даже пытался вызвать непубличные методы объекта BandsCollection, такие как "ClearAllButBandZero" и "Clear", но все это было безрезультатно.

Я нашел предмет в базе знаний DevCenter по инфраструктуре: http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.Aspx?ArticleID=1751 но это не помогло в моем случае. Каждый раз, когда DataSet восстанавливается, коллекция UltraGrid.DisplayLayout.Bands становится все более и более грязной.

2 ответа

Решение

Я нашел, что вызывает такое поведение. Это ошибка в.NET Framework. В классе BindingSource есть приватное поле:

private Dictionary<string, BindingSource> relatedBindingSources;

Проблема в том, что после того, как вы присвоите null вашему BindingSource.DataSource, словарь останется нетронутым. Затем вы назначаете новый источник данных, добавляете в него отношение, словарь увеличивается. И никогда не останавливается.

Моим решением этой проблемы было создание простого метода, который убедит меня, что все возможные отношения удалены:

    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, благодаря которому я начал копать в нужном месте;)

Нет необходимости использовать 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();
    }

}
Другие вопросы по тегам