Problema de enlace de datos de WinForms ComboBox
-
08-06-2019 - |
Pregunta
Suponga que está haciendo algo como lo siguiente
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
Ahora tenemos 2 cuadros combinados vinculados a esa 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 (lo aprendí cuando aprendí C: D), pero ¿por qué los cuadros combinados cambiarían juntos?No creo que el control del cuadro combinado esté modificando la colección en absoluto.
Como solución alternativa, ¿no lograría esto la funcionalidad esperada o deseada?
ComboBox box = new ComboBox();
box.DataSource = myitems.ToArray();
Solución
Esto tiene que ver con cómo se configuran los enlaces de datos 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 lo mismo. BindingContext
.Cuando estás configurando el DataSource
propiedad la ComboBox
utilizará el BindingContext
conseguir un ConcurrenyMangager
eso envuelve la lista.El ConcurrenyManager
realiza un seguimiento de cosas tales como la posición seleccionada actualmente en la lista.
Cuando configuras el DataSource
del segundo ComboBox
usará lo mismo BindingContext
(los formularios) que darán como resultado una referencia al mismo ConcurrencyManager
como se utiliza arriba para configurar los enlaces de datos.
Para obtener una explicación más detallada consulte Contexto vinculante.
Otros consejos
Una mejor solución (dependiendo del tamaño de la fuente de datos) es declarar dos BindingSource
Los objetos (nuevos a partir de 2.00) vinculan la colección a aquellos y luego los vinculan 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 declarar siempre enlaces en el constructor.Eso puede resultar en algunos en realidad errores curiosos, por eso siempre me vinculo en el evento Load.