2009-05-20 6 views
8

J'ai un ComboBox lié à un DataSource. Je souhaite ajouter des éléments de manière dynamique à la zone de liste déroulante en fonction de certaines conditions. Donc ce que je l'ai fait est d'ajouter les options à une nouvelle liste, puis modifiez le DataSource du ComboBox comme ceci:ComboBox items.count ne correspond pas à la source de données (C#)

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

Ensuite, je vérifie cbo.Items.Count, et il n'a pas incrémentée - il ne correspond pas à la nombre de DataSource. Des idées que je peux faire ici? Notez que c'est WinForms et non asp.net.

Merci

+2

Avez-vous vérifié la propriété .Count avant ou après que la liste déroulante ait été déroulée? Je pense qu'il y a des optimisations qui sont faites pour éviter de recharger la collection d'objets trop souvent, donc cela pourrait retarder le tout jusqu'à ce que vous le laissiez tomber à l'écran. –

+0

Quelle version de .NET est-ce? Dans Visual Studio 2008, la compilation pour 2.0 ou 3.5 produit le nombre correct d'éléments à la fois. –

+1

Je reçois ce problème dans VS2012 avec une zone de liste déroulante créée dynamiquement –

Répondre

6

Si quelqu'un rencontre ce problème sur une zone de liste déroulante ajoutée dynamiquement, la réponse est de s'assurer que vous ajoutez la zone de liste déroulante aux contrôles d'un conteneur dans le formulaire.

En ajoutant "this.Controls.Add (cbo);" au code avant de définir la source de données, le problème disparaît.

+0

-1, faux. Cela arrive aussi si le ComboBox est déjà contenu dans un conteneur qui n'a pas encore de handle Windows. – TheBlastOne

+0

Je ne pense pas que -1 soit juste ici, juste parce que vous avez trouvé une autre raison que cela se produit. Cette réponse a résolu le problème dans l'exemple indiqué. – Madeleine

+0

Impossible d'annuler à moins que la réponse soit éditée. Je continue à me demander quel genre de règles d'édition sont derrière donc le frontend ... – TheBlastOne

12

Avez-vous vérifié le comte immédiatement ou à une date ultérieure? Il y a la possibilité que le ComboBox ne met pas réellement son contenu à jour jusqu'à ce qu'il y ait une opération telle qu'une actualisation de l'interface utilisateur et par conséquent le compte sera désactivé jusqu'à ce moment.

Dans le cas où cela peut se produire est si vous mettez à jour le DataSource avant que le handle soit créé pour le ComboBox. J'ai creusé un peu le code sur le réflecteur et il semble que les éléments ne seront pas mis à jour dans ce cas jusqu'à ce que le ComboBox soit réellement créé et rendu.

+1

Je vérifie la propriété Items.Count immédiatement après le code, car je dois alors faire un peu plus de logique à ce moment-là. – Madeleine

+0

Ne serait-il pas plus simple de vérifier le nombre d'éléments dans votre source de données? – scraimer

+0

Le problème est que je dois définir l'élément sélectionné, généralement à la nouvelle, et cet index n'existe pas. – Madeleine

0

Il y a aussi un « DataSourceChanged » -event ... peut-être que cela pourrait aider

0

Juste pour préciser que vous appelez la méthode count() Après avoir appelé la DataBind() méthode

+0

Ceci est un combobox winforms, il n'y a pas databind() –

5

J'ai trouvé la cause ...

J'ai retiré la ligne cbo.Datasource = null et ajouté un cbo.Invalidate() à la fin. Cela a résolu le problème.

Merci à tous pour le conseil.

+1

Trouvé votre propre solution. Allez-y et acceptez votre propre réponse. +1 –

+0

Vous devriez avoir ajouté cette ligne avant de définir la source de données. 'cbo.Items.clear()' –

0

Ce code produit 2 dans la boîte de message pour moi, pouvez-vous l'essayer et voir comment il se comporte pour vous? Vous pouvez le coller dans une application de console et ajouter une référence à System.Windows.Forms et 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; // toujours zéro

BindingContext dummy = this.comboBox1.BindingContext; // Forcer la mise à jour MAINTENANT!

int c2 = comboBox1.DataSource.Count; // maintenant égal somelist.Count

+0

Ne fonctionne pas, désolé. – TheBlastOne

-1

Ba salam,

vous pouvez simplement rafraîchir l'interface utilisateur en fonction preformLayout();

Exemple:

comboBox1.performLayout();

ce qui concerne s mohsen

+0

Ne fonctionne pas. Pardon. – TheBlastOne

-1

s'il vous plaît essayez ceci:

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

Je pense que votre question SAMES comme je l'ai rencontré aujourd'hui.

0

J'ai eu le même problème (Im travaillant avec VS 2005). Ce que vous devez faire est de définir le DataSource à null, effacer les éléments, réaffecter la source de données, afficher et évaluer les membres.

Exemples

cbo.DataSource = null;

cbo.Items.Clear();

cbo.DataSource = cbos;

cbo.DisplayMember = "Titre";

cbo.ValueMember = "Valeur";

+0

Fonctionne uniquement si ComboBox a déjà obtenu un handle Windows. – TheBlastOne

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

Maintenant, avant de cbo.SelectedValue, ou se fondant sur Items pour être à jour, appelez

cbo.CreateControl ; 

et Items seront recalculées.

Le problème est que SelectedValue/SelectedIndex, qui sont des propriétés WinForms, acceptent que les valeurs qui sont légales selon la liste Items, mais que l'on est construit seulement après l'interaction GUI, soit après l'instanciation d'un « vrai » combo GUI Windows boîte, c'est à dire après avoir obtenu un handle Windows pour la liste déroulante.

CreateControl force la création de la poignée Windows, quoi qu'il arrive.

+0

CreateControl n'a pas résolu le problème pour moi. Ajout du contrôle à la collection a fait. – Brad

+1

L'ajout de CreateControl a fonctionné pour moi –

0

Ancien thread, mais j'ai essayé certaines de ces solutions, ainsi que la suspension/reprise du bindingcontext, la liaison et la réinitialisation d'une source de liaison, et le simple rechargement du formulaire. Aucun n'a travaillé pour mettre à jour mon contrôle avec les données nouvellement liées au moment de mon paramètre .datasource (mon items.count était vide, tout comme l'OP).

Ensuite, j'ai réalisé que ma combobox se trouvait sur une tabulation qui était supprimée au début du code, et plus tard rajoutée (après ma liaison de données). L'événement de liaison n'a pas eu lieu jusqu'à la page à onglet a été ajoutée à nouveau.

Cela semble évident rétrospectivement, mais il était très difficile à détecter à l'exécution, en raison de l'ordre des appels et de l'incapacité de voir quand les choses changeaient.

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

À

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"; 

Le DataSource, propriété DisplayMember et ValueMember doit être réglé après que la commande a été ajouté à son récipient.