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