Gotcha

2008-08-02 15 views
43

enlace de datos WinForms ComboBox Suponga que está haciendo algo como lo siguienteGotcha

List<string> myitems = new List<string> 
{ 
    "Item 1", 
    "Item 2", 
    "Item 3" 
}; 

ComboBox box = new ComboBox(); 
box.DataSource = myitems; 

ComboBox box2 = new ComboBox(); 
box2.DataSource = myitems 

Así que ahora tenemos 2 cuadros combinados con destino a la matriz, y todo funciona bien. Pero cuando cambia el valor de un cuadro combinado, cambia AMBOS cuadros combinados al que acaba de seleccionar.

Ahora, sé que las matrices siempre se pasan por referencia (aprendí eso cuando aprendí C: D), pero ¿por qué en la tierra cambiarían los cuadros combinados? No creo que el control del cuadro combinado modifique la colección.

Como solución, no hacerlo sería lograr el funcionalidad que se espera/deseada

ComboBox box = new ComboBox(); 
box.DataSource = myitems.ToArray(); 

Respuesta

36

Esto tiene que ver con la forma en enlaces de datos se configuran en el marco dotnet, especialmente el BindingContext. En un nivel alto, significa que si no ha especificado lo contrario, cada formulario y todos los controles del formulario comparten el mismo BindingContext. Cuando establezca la propiedad DataSource, el ComboBox usará el BindingContext para obtener un ConcurrenyMangager que envuelve la lista. El ConcurrenyManager realiza un seguimiento de cosas tales como la posición seleccionada actual en la lista.

Cuando se establece el DataSource de la segunda ComboBox que utilizará los mismos BindingContext (las formas) que producirá una referencia a la misma ConcurrencyManager como anteriormente se utiliza para establecer los enlaces de datos.

Para obtener una explicación más detallada, ver BindingContext.

+1

Parece un gran esfuerzo no proporcionar ningún beneficio y hacer que los controles de enlace de datos sean completamente contra-intuitivos. – Belmiris

19

Una mejor solución (dependiendo del tamaño de la fuente de datos) es declarar dos objetos BindingSource (nuevos a partir de 2.00) vincular la colección a esos y luego vincularlos a los cuadros combinados.

Adjunto un ejemplo completo.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     private BindingSource source1 = new BindingSource(); 
     private BindingSource source2 = new BindingSource(); 

     public Form1() 
     { 
      InitializeComponent(); 
      Load += new EventHandler(Form1Load); 
     } 

     void Form1Load(object sender, EventArgs e) 
     { 
      List<string> myitems = new List<string> 
      { 
       "Item 1", 
       "Item 2", 
       "Item 3" 
      }; 

      ComboBox box = new ComboBox(); 
      box.Bounds = new Rectangle(10, 10, 100, 50); 
      source1.DataSource = myitems; 
      box.DataSource = source1; 

      ComboBox box2 = new ComboBox(); 
      box2.Bounds = new Rectangle(10, 80, 100, 50); 
      source2.DataSource = myitems; 
      box2.DataSource = source2; 

      Controls.Add(box); 
      Controls.Add(box2); 
     } 
    } 
} 

Si quiere confundirse aún más, intente siempre declarar enlaces en el constructor. Eso puede resultar en algunos realmente errores curiosos, por lo tanto, siempre se unen en el evento Load.

+1

Gracias por indicar que el enlace en el constructor da como resultado algunos errores realmente curiosos. Tuve un problema similar y moví mi código al evento Load y mostró los datos vinculados. – bunggo

+0

He encontrado algunos de los errores más extraños no reportados con eso. En el peor de los casos, un cuadro combinado se negó a centrar su atención en ningún otro control: D – Quibblesome

1

Esto podría ser simplemente un error tipográfico, pero en el código que siempre que la única referencia el primer cuadro combinado al configurar el origen de datos:

ComboBox box = new ComboBox(); 
box.DataSource = myitems; 

ComboBox box2 = new ComboBox(); 
**box**.DataSource = myitems 

La fuente de datos para box2 no está establecida.

Cuestiones relacionadas