2009-05-20 14 views
8

Tengo un ComboBox que está vinculado a un DataSource. Quiero agregar elementos dinámicamente al ComboBox según ciertas condiciones. Así que lo que he hecho es añadir las opciones para una nueva lista, y luego cambiar el origen de datos del cuadro combinado de este modo:ComboBox items.count doesnt match datasource (C#)

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

Entonces, puedo comprobar cbo.Items.Count, y no ha incrementado - que no es igual al cuenta del DataSource. ¿Alguna idea de lo que puedo hacer aquí? Tenga en cuenta que esto es WinForms y no asp.net.

Gracias

+2

¿Revisó la propiedad .Count antes o después de que se desplegara el menú desplegable? Sospecho que se realizan algunas optimizaciones para evitar volver a cargar la colección de elementos con demasiada frecuencia, por lo que podría posponer todo el asunto hasta que realmente lo dejes caer en la pantalla. –

+0

¿Qué versión de .NET es esto? En Visual Studio 2008, compilar para 2.0 o 3.5 produce la cantidad correcta de elementos a la vez. –

+1

Obtengo este problema en VS2012 con un cuadro combinado creado dinámicamente –

Respuesta

6

Si alguien experimenta este problema en un cuadro combinado agregado dinámicamente, la respuesta es asegurarse de agregar el cuadro combinado a los controles de un contenedor en el formulario.

Al agregar "this.Controls.Add (cbo);" al código antes de establecer la fuente de datos, el problema desaparece.

+0

-1, falso. Ocurre también si el ComboBox ya está contenido en un contenedor que aún no tiene un controlador de Windows. – TheBlastOne

+0

No creo que un -1 sea justo aquí, solo porque ha encontrado otra razón por la que esto ocurre. Esta respuesta resolvió el problema en el ejemplo indicado. – Madeleine

+0

No se puede deshacer a menos que se edite la respuesta. Me sigo preguntando qué tipo de reglas de edición están detrás de la interfaz ... – TheBlastOne

12

¿Ha comprobado el conde inmediatamente o en un momento posterior? Existe la posibilidad de que el ComboBox no actualice sus contenidos hasta que haya una operación como una actualización de UI y, por lo tanto, el conteo estará desactivado hasta ese momento.

En caso de que esto ocurra es si actualiza el DataSource antes de crear el controlador para el ComboBox. Excavé un poco el código en el reflector y parece que los elementos no se actualizarán en este caso hasta que realmente se haya creado y procesado el ComboBox.

+1

Estoy comprobando la propiedad Items.Count inmediatamente después en el código, porque entonces necesito hacer un poco más de lógica en ese punto. – Madeleine

+0

¿No sería más sencillo verificar la cantidad de elementos en su fuente de datos? – scraimer

+0

El problema es que tengo que establecer el elemento seleccionado, generalmente al nuevo, y ese índice no existe. – Madeleine

0

También hay un -Evento "DataSourceChanged" ... tal vez eso podría ayudar a

0

sólo para aclarar estas llamando el método de conteo() Después de llamar al método DataBind()

+0

Este es un cuadro combinado de winforms, no hay databind() –

5

que he encontrado la causa ...

Saqué la línea cbo.Datasource = null .. y agregué un cbo.Invalidate() al final. Esto ha resuelto el problema.

Gracias a todos por el consejo.

+1

Encontrado su propia solución. Adelante, acepta tu propia respuesta. +1 –

+0

Debería haber agregado esta línea antes de configurar el origen de datos. 'cbo.Items.clear()' –

0

Este código produce 2 en el cuadro de mensaje para mí, ¿puedes probarlo y ver cómo se comporta para ti?

Puede pegarlo en una aplicación de consola y agregar una referencia a System.Windows.Forms y 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; // todavía cero

BindingContext dummy = this.comboBox1.BindingContext; // Force update NOW!

int c2 = comboBox1.DataSource.Count; // ahora es igual a somelist.Count

+0

No funciona, lo siento. – TheBlastOne

-1

Salam Ba,

puede simplemente refrescar la interfaz de usuario mediante la función preformLayout();

Ejemplo:

comboBox1.performLayout();

respecto Mohsen s

+0

No funciona. Lo siento. – TheBlastOne

-1

favor intente esto:

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

Creo que su Sames pregunta como me encontré hoy.

0

Tuve el mismo problema (estoy trabajando con VS 2005).

Lo que necesita hacer es establecer DataSource en nulo, borrar los elementos, reasignar la fuente de datos, mostrar y valorar los miembros.

Ej

cbo.DataSource = null;

cbo.Items.Clear();

cbo.DataSource = cbos;

cbo.DisplayMember = "Título";

cbo.ValueMember = "Valor";

+0

Funciona solo si el ComboBox ya obtuvo un identificador de Windows. – TheBlastOne

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

Ahora antes de cbo.SelectedValue, o confiar en Items para estar al día, llamada se recalculan

cbo.CreateControl ; 

y Items.

El problema es que SelectedValue/SelectedIndex, que son WinForms propiedades, sólo aceptan los valores que son legales de acuerdo a la lista Items, pero que uno se construye sólo después de la interacción interfaz gráfica de usuario, es decir, después de crear instancias de un "verdadero" combo GUI de Windows cuadro, es decir, después de obtener un identificador de Windows para el cuadro combinado.

CreateControl fuerza la creación del controlador de Windows, no importa qué.

+0

CreateControl no solucionó el problema por mí. Agregar el control a la colección sí. – Brad

+1

Agregar CreateControl funcionó para mí –

0

Tema viejo, pero probé algunas de estas soluciones, junto con suspender/reanudar el contexto de enlace, enlazar y restablecer un origen de enlace y simplemente volver a cargar el formulario. Ninguno funcionó para actualizar mi control con los datos nuevos enlazados en el momento de mi configuración de .datasource (mi cuenta de artículos estaba vacía, al igual que el OP).

Luego me di cuenta de que mi combobox estaba en un tabulador que se eliminaba al comienzo del código, y luego se volvió a agregar (después de mi enlace de datos). El evento de enlace no se produjo hasta se volvió a agregar el tabulador.

Parece obvio en retrospectiva, pero fue muy difícil de detectar en tiempo de ejecución, debido al orden de las llamadas y la incapacidad de ver cuando las cosas estaban cambiando.

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

A

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

la fuente de datos, DisplayMember y ValueMember propiedad se debe establecer después de que el control ha sido añadido a su contenedor.