7

Winformsの複数選択リストボックスを動的に作成し、それをフローパネルコントロールに追加しています。作成したオブジェクトからデータソースをバインドし、データソースに実際に約14個の要素があることを確認しました。実行するlistBox.SetSelected(0, true)と、System.ArgumentOutOfRangeExceptionエラーがスローされます。

問題は、データソースには14個の要素がありますが、アイテムコレクションには何も(0)がないため、例外がスローされることであると判断しました。私の質問は、なぜこれら2つが互いに異なるのか、そしてなぜデータソースのforeachアイテムをアイテムコレクションに追加しないのかということです。

以下は私がこれまでに持っているコードです:

case InsertableItemParameter.ParameterType.ListBox:
    //note: two-way bindings are not possible with multiple-select listboxes
    Label lblListBox = new Label();
    lblListBox.Text = param.DisplayText;
    ListBox listBox = new ListBox();
    listBox.DataSource = param.Values;
    listBox.DisplayMember = "Value";
    listBox.SelectionMode = SelectionMode.MultiExtended;
    listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
    listBox.SetSelected(0, true);   //will throw argument out of range exception here!
    listBox.SetSelected(1, true);
    flowPanel.Controls.Add(lblListBox);
    flowPanel.Controls.Add(listBox);
    flowPanel.SetFlowBreak(listBox, true);
    break;

以下は、私が試し、実行した代替ソリューションですが、なぜデータソースとアイテムのコレクションを使用するのでしょうか。

case InsertableItemParameter.ParameterType.ListBox:
    //note: two-way bindings are not possible with multiple-select listboxes
    Label lblListBox = new Label();
    lblListBox.Text = param.DisplayText;
    ListBox listBox = new ListBox();
    //listBox.DataSource = param.Values;
    listBox.DisplayMember = "Value";
    listBox.SelectionMode = SelectionMode.MultiExtended;
    listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
    listBox.BeginUpdate();
    foreach (String paramater in param.Values)
    {
        listBox.Items.Add(paramater);
    }
    listBox.EndUpdate();
    listBox.SetSelected(0, true);
    listBox.SetSelected(1, true);
    flowPanel.Controls.Add(lblListBox);
    flowPanel.Controls.Add(listBox);
    flowPanel.SetFlowBreak(listBox, true);
    break;

回答:すべての回答に感謝します。ここでの問題は、可視性とウィンフォームレンダリングです。DataSourceコレクションとItemsコレクションの違いは、少数の人を除いて実際には対処されていませんでしたがSetSelected()、フォームの描画が完了した後にメソッドを呼び出すことで、私の問題の本当の原因は解決されました。これにより、アプリケーションの設計で解決しなければならない多くの問題が発生しますが、これが問題でした。私が答えとしてマークした返信を参照してください。

4

5 に答える 5

4

このコードは正常に動作するため、問題はおそらく別の場所にあります。

string[] ds = {"123","321"};
listBox1.DataSource = ds;
listBox1.SetSelected(1, true);
MessageBox.Show(listBox1.Items.Count.ToString()); //returns 2

フォームに配置された新しい C# プロジェクトでテストされlistBox1、上記のコードはForm_Load.

編集:実行時に a を作成すると違いが生じることに気づきませんでしたListBox。特に、選択した項目をいつ設定するかが重要であるためです。このコードは機能します:

string[] ds = { "123", "321" };
ListBox lst = new ListBox();
lst.DataSource = ds;
lst.Size = new Size(100,100);            
this.Controls.Add(lst);
//make sure to call SetSelected after adding the ListBox to the parent
lst.SetSelected(1, true);

これを指摘してくれた@Bradに感謝します。元の質問に戻って、これを置き換えます。

listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);

これとともに:

flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);

そして、それはうまくいくはずです。

于 2013-03-04T18:51:40.290 に答える
2

でデータを取得する方法には 2 つのオプションがありますListBox。を設定するDataSourceか、 を介して項目を手動で追加できますlistBox.Items.Add(paramater)。お互いに踏むため、両方を行うことはできません。したがって、エラーが発生します

...cannot add items to the Item collection when DataSource is set.
于 2013-03-04T18:50:33.100 に答える
1

2 つの異なるコレクションがある理由がわかりません。Itemsプロパティはよりシンプルに見えます。

私は例外の理由を見つけました:明らかに、次のように特定の順序で物事を行う必要があります:

    //init the listbox
    var listBox1 = new ListBox();
    listBox1.Location = new System.Drawing.Point(122, 61);
    listBox1.Size = new System.Drawing.Size(205, 147);
    listBox1.SelectionMode = SelectionMode.MultiExtended;
    Controls.Add(listBox1); //<-- point of interest

    //then set the DataSource
    listBox1.DataSource = lst;
    listBox1.DisplayMember = "Name";
    listBox1.ValueMember = "Age";

    //then set the selected values
    listBox1.SetSelected(0, true);
    listBox1.SetSelected(1, true);

Testのクラスは次のようになります。

public class Test
{
    private static Random r = new Random();
    public Test (string name)
    {
        Name = name;
        Age = r.Next(16, 45);
    }

    public string Name { get; set; }

    public int Age{ get; set; }
}

そしてlst、次のように宣言されています。

    var lst = new List<Test>()
                  {
                      new Test("jens"),
                      new Test("Tom"),
                      new Test("John"),
                      new Test("Don"),
                      new Test("Jenny"),
                  };
于 2013-03-04T18:53:50.747 に答える
1

MSDN のアイテム

このプロパティを使用すると、ListBox に現在格納されている項目のリストへの参照を取得できます。この参照を使用して、アイテムの追加、アイテムの削除、およびコレクション内のアイテムの数の取得を行うことができます。アイテム コレクションで実行できるタスクの詳細については、ListBox.ObjectCollection クラスのリファレンス トピックを参照してください。

MSDNからのデータソース

DataSet や Array などの IList または IListSource インターフェイスを実装するオブジェクト。デフォルトはヌルです

私はこの問題の専門家ではありませんが、私が読んだところによると、Items ではリストの内容を追加/変更でき、Datasource では内容を取得して設定できるようです。

于 2013-03-04T18:43:58.757 に答える
1

コントロールが表示されている場合にのみ、Items コレクションが DataSource から取り込まれます。コントロールを動的に作成するため、親コントロールに追加されず、表示されません。したがって、最初に画面に表示されるコントロールが必要です。コードで DataSource を設定し、コントロールに追加されていないため、選択した項目をControl表示する前に設定します。ステートメントの順序を変更する必要があります。を追加して、実行できるメソッドから Items コレクションを作成する必要があります。これを試して、最初のコードの実行順序が変更されていることに注意してください。FlowChartParentlistBoxFlowPanelDataSourceSetSelected()

ListBox listBox = new ListBox();
listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox); //notice that you first add the listBox to the flowChart
listBox.SetSelected(0, true);   //and then you have items in the Items collection which you can select
listBox.SetSelected(1, true);
于 2013-03-04T18:55:28.963 に答える