1

UltraGridBandsメカニズムの奇妙な動作を理解しようと頭を悩ませています。以下のコードには、問題を再現するために必要なすべてのものが含まれています。

DataSetを作成し、2つのDataTableで埋めています。次に、DataSetをBindingSourceオブジェクトのデータソースとして割り当てます。そのBindingSourceオブジェクトはUltraGrid.DataSourceとして設定されます。

以下のコードは、単一のPrepareData()メソッドが起動された後に何が起こっているかを完全に理解するのに役立ちます。グリッドには3つのレコードが表示され、最初のレコードは展開可能で、DataRelationによって参照される2番目のバンドが表示されます。2番目の呼び出しをコメントアウトすることで確認できます。

    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()メソッドをもう一度実行すると、グリッドが乱雑になります。私は実際に問題の原因を見つけたので、上記のコードに重いコメントがありますが、なぜこれが起こっているのか理解できません。結果として、メソッドが何度呼び出されても、グリッドがまったく同じように動作するようにしたいだけです。

誰かがこれの理由が何であるかについての手がかりを持っていますか?

私はすでにデータソースを無効にして、それらを再割り当てしようとしました。呼び出されるメソッドの順序を変更するのにうんざりしていました。「ClearAllButBandZero」や「Clear」などのBandsCollectionオブジェクトの非公開メソッドを呼び出そうとしましたが、まったく役に立ちませんでした。

Infragistics DevCenterのナレッジベース( http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.Aspx?ArticleID=1751 )でアーティブルを見つけました が、私の場合は役に立ちませんでした。DataSetが再構築されるたびに、UltraGrid.DisplayLayout.Bandsコレクションはますます乱雑になっています。

4

2 に答える 2

1

私はそのような行動を引き起こしているものを見つけました。これは .NET Framework のバグです。BindingSource クラスにはプライベート フィールドがあります。

private Dictionary<string, BindingSource> relatedBindingSources;

問題は、BindingSource.DataSource に null を割り当てると、Dictionary が変更されないことです。次に、新しい 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 プロパティを null にしてから、そのメソッドを呼び出すだけです。これにより、グリッド内のバンド複製の問題が本質的に解決されました。

私が正しい場所で掘り始めてくれたThanasisに感謝します;)

于 2012-12-13T16:18:17.287 に答える
1

データセットを UltraGrid のデータソースとして追加するために BindingSource を使用する必要はありません。データセットをグリッドのデータソースとして直接割り当てることができます。次のコードを見てください。

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 に答える