2009-05-20 14 views
8

Mam ComboBox, który jest powiązany z DataSource. Chcę dynamicznie dodawać elementy do ComboBox na podstawie pewnych warunków. Więc co zrobiłem jest dodanie opcji do nowej listy, a następnie zmienić DataSource z ComboBox tak:ComboBox items.count nie pasuje do źródła danych (C#)

cbo.DataSource = null; 
cbo.DataSource = cbos; 
cbo.DisplayMember = "Title"; 
cbo.ValueMember = "Value"; 

Potem sprawdzić cbo.Items.Count i nie zwiększa się - to nie równa się liczba źródeł danych. Jakieś pomysły, co mogę tutaj zrobić? Zauważ, że to jest WinForms, a nie asp.net.

Dzięki

+2

Czy sprawdziłeś właściwość .Count przed lub po opuszczeniu menu rozwijanego? Podejrzewam, że są wykonywane pewne optymalizacje, aby zbyt często nie ładować kolekcji przedmiotów, więc może to odroczyć całość, dopóki nie upuścisz go na ekran. –

+0

Która wersja .NET to jest? W Visual Studio 2008 kompilacja dla wersji 2.0 lub 3.5 generuje poprawną liczbę elementów naraz. –

+1

Otrzymuję ten problem w VS2012 z dynamicznie utworzonym comboboxem –

Odpowiedz

6

Jeśli ktoś ma ten problem na dynamicznie dodanym comboboxie, odpowiedzią jest, aby dodać combobox do formantów kontenera w formularzu.

Dodając "this.Controls.Add (cbo);" do kodu przed ustawieniem źródła danych, problem znika.

+0

-1, nieprawdziwe. Dzieje się tak również wtedy, gdy ComboBox jest już zawarty w kontenerze, który nie ma jeszcze uchwytu systemu Windows. – TheBlastOne

+0

Nie sądzę, że -1 jest tutaj sprawiedliwe, tylko dlatego, że znalazłeś inny powód, dla którego tak się dzieje. Ta odpowiedź rozwiązała problem w podanym przykładzie. – Madeleine

+0

Nie można cofnąć, dopóki odpowiedź nie zostanie zmieniona. Zastanawiam się, jakie reguły edycji są za tak frontend ... – TheBlastOne

12

Czy sprawdziłeś hrabiego natychmiast lub w późniejszym czasie? Istnieje możliwość, że ComboBox nie aktualizuje jej zawartości, dopóki nie zostanie wykonana operacja, taka jak odświeżenie interfejsu, a zatem liczba ta będzie wyłączona do tego czasu.

W przypadku, gdy może się to zdarzyć, należy zaktualizować DataSource, zanim uchwyt zostanie utworzony dla składnika ComboBox. Odkopałem trochę kod na reflektorze i wygląda na to, że elementy nie będą w tym przypadku aktualizowane, dopóki ComboBox nie zostanie faktycznie utworzony i renderowany.

+1

Sprawdzam właściwość Items.Count natychmiast po tym, jak w kodzie, ponieważ potrzebuję wtedy zrobić trochę więcej logiki w tym punkcie. – Madeleine

+0

Czy nie byłoby łatwiej sprawdzić liczbę elementów w źródle danych? – scraimer

+0

Problem polega na tym, że muszę ustawić wybrany element, zwykle na nowy, a ten indeks nie istnieje. – Madeleine

0

Jest też „DataSourceChanged” -event ... może mogłaby pomóc

0

prostu do wyjaśnienia dzwonisz metoda count() Po wywołaniu DataBind() metoda

+0

To jest combobox, nie ma databind() –

5

Znalazłem przyczyna ...

Wyjąłem cbo.Datasource = null line .. i dodałem cbo.Invalidate() na końcu. To rozwiązało problem.

Dziękuję wszystkim za radę.

+1

Znaleziono własne rozwiązanie. Śmiało i zaakceptuj własną odpowiedź. +1 –

+0

Powinieneś raczej dodać tę linię przed ustawieniem źródła danych. 'cbo.Items.clear()' –

0

Ten kod generuje dla mnie 2 w polu wiadomości, czy możesz spróbować i zobaczyć, jak się on zachowuje?

Możesz wkleić go do aplikacji konsolowej i dodać odniesienie do System.Windows.Forms i System.Drawing.

using System; 
using System.Collections.Generic; 
using System.Windows.Forms; 
using System.Drawing; 

namespace SO887803 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      Application.Run(new MainForm()); 
     } 
    } 

    public partial class MainForm : Form 
    { 
     private Button _Button; 
     private ComboBox _ComboBox; 

     public MainForm() 
     { 
      _Button = new Button(); 
      _Button.Text = "Test"; 
      _Button.Location = new Point(8, 8); 
      _Button.Click += _Button_Click; 
      Controls.Add(_Button); 

      _ComboBox = new ComboBox(); 
      _ComboBox.Location = new Point(8, 40); 
      Controls.Add(_ComboBox); 
     } 

     private void _Button_Click(object sender, EventArgs e) 
     { 
      List<Item> items = new List<Item>(); 
      items.Add(new Item("A", "a")); 
      items.Add(new Item("B", "b")); 

      _ComboBox.DataSource = null; 
      _ComboBox.DataSource = items; 
      _ComboBox.DisplayMember = "Title"; 
      _ComboBox.ValueMember = "Value"; 
      MessageBox.Show("count: " + _ComboBox.Items.Count); 
     } 

     public class Item 
     { 
      public String Title { get; set; } 
      public String Value { get; set; } 
      public Item(String title, String value) 
      { 
       Title = title; 
       Value = value; 
      } 
     } 
    } 
} 
0

comboBox1.DataSource = somelist;

int c1 = comboBox1.DataSource.Count; // nadal zero

BindingContext dummy = this.comboBox1.BindingContext; // Wymuś aktualizację TERAZ!

int c2 = comboBox1.DataSource.Count; // teraz równa somelist.Count

+0

Nie działa, przepraszam. – TheBlastOne

-1

Ba Salam,

można po prostu odświeżyć interfejs przez preformLayout funkcji();

Przykład:

comboBox1.performLayout();

pozdrowienia Mohsen s

+0

Nie działa. Przepraszam. – TheBlastOne

-1

spróbuj to:

cbo.Parent = <your panel control>; 
cbo.DataSource = null; 
cbo.DataSource = cbos; cbo.DisplayMember = "Title"; 
cbo.ValueMember = "Value"; 
MessageBox.Show(string.Format("itemcount is {0}", cbo.Items.Count); 

myślę swoich SAMES pytanie jakbym spotkał się dzisiaj.

0

Miałem ten sam problem (pracuję z VS 2005).

To, co musisz zrobić, to ustawić źródło danych na wartość null, wyczyścić elementy, ponownie przypisać źródło danych, wyświetlić i wartościować elementy.

Np.

cbo.DataSource = null;

cbo.Items.Clear();

cbo.DataSource = cbos;

cbo.DisplayMember = "Tytuł";

cbo.ValueMember = "Wartość";

+0

Działa tylko wtedy, gdy ComboBox już uzyskał uchwyt systemu Windows. – TheBlastOne

4
cbo.DataSource = null; 
cbo.DataSource = cbos; 
cbo.DisplayMember = "Title"; 
cbo.ValueMember = "Value"; 

teraz przed ustawieniem cbo.SelectedValue lub opierając się na Items być na bieżąco, zadzwoń zostanie ponownie obliczona

cbo.CreateControl ; 

i Items.

Problemem jest to, że SelectedValue/SelectedIndex, które są WinForms właściwości, przyjąć tylko wartości, które są legalne, według listy Items, ale jeden jest zbudowany dopiero po interakcji GUI, czyli po uruchamianiu „prawdziwy” Windows GUI combo box, czyli po uzyskaniu uchwytu Windows dla combobox.

wymusza tworzenie klamki systemu Windows, bez względu na wszystko.

+0

CreateControl nie rozwiązał problemu dla mnie. Dodano kontrolę do kolekcji. – Brad

+1

Dodawanie CreateControl pracował dla mnie –

0

Stary wątek, ale wypróbowałem niektóre z tych rozwiązań, wraz z zawieszeniem/wznowieniem powiązanego tekstu, powiązaniem i zresetowaniem powiązanego źródła oraz zwykłym ponownym załadowaniem formularza. Żaden nie pracował nad zaktualizowaniem kontroli nad nowo powiązanymi danymi w czasie mojego ustawienia .datasource (mój items.count był pusty, podobnie jak OP).

Potem zdałem sobie sprawę, że mój combobox był na stronie, która została usunięta na początku kodu, a później ponownie dodana (po mojej kopii danych). Zdarzenie wiązania nie wystąpiło, dopóki nie zostanie ponownie dodana strona tytułowa.

Wydaje się oczywiste z perspektywy czasu, ale było bardzo trudne do wykrycia w czasie wykonywania, ze względu na kolejność połączeń i brak możliwości sprawdzenia, kiedy coś się zmieniło.

0
ComboBox cbNew = new ComboBox(); 
    cbNew.Name = "cbLine" + (i+1); 
    cbNew.Size = cbLine1.Size; 
    cbNew.Location = new Point(cbLine1.Location.X, cbLine1.Location.Y + 26*i); 
    cbNew.Enabled = false; 
    cbNew.DropDownStyle = ComboBoxStyle.DropDownList; 
    cbNew.DataSource = DBLayer.GetTeams(lineName).Tables[0]; 
    cbNew.DisplayMember = "teamdesc"; 
    cbNew.ValueMember = "id"; 
    Console.WriteLine("ComboBox {0}, itemcount={1}", cbNew.Name, cbNew.Items.Count); 
     // The output displays itemcount = 0 for run-time created controls 
     // and >0 for controls created at design-time 
    gbLines.Controls.Add(cbNew); 

DO

ComboBox cbNew = new ComboBox(); 
    cbNew.Name = "cbLine" + (i+1); 
    cbNew.Size = cbLine1.Size; 
    cbNew.Location = new Point(cbLine1.Location.X, cbLine1.Location.Y + 26*i); 
    cbNew.Enabled = false; 
    cbNew.DropDownStyle = ComboBoxStyle.DropDownList; 
    Console.WriteLine("ComboBox {0}, itemcount={1}", cbNew.Name, cbNew.Items.Count); 
     // The output displays itemcount = 0 for run-time created controls 
     // and >0 for controls created at design-time 
    gbLines.Controls.Add(cbNew); 
    cbNew.DataSource = DBLayer.GetTeams(lineName).Tables[0]; 
    cbNew.DisplayMember = "teamdesc"; 
    cbNew.ValueMember = "id"; 

źródła danych, DisplayMember i ValueMember właściwość musi być ustawiony po kontroli został dodany do jego pojemnika.

Powiązane problemy