una - ocultar columna datagridview c#
¿Cómo se puede evitar que el diseñador de Visual Studio genere columnas automáticamente en un DataGridView? (10)
He visto este comportamiento antes para ComboBox con la propiedad Items y es realmente frustrante. Así es como lo he manejado con ComboBox. Debería poder aplicar esto a DataGridView.
Creé una propiedad "nueva" llamada Items y la configuré para que no se pueda explorar y para que se oculte explícitamente de la serialización. Debajo del capó solo accede a la propiedad de Artículos reales.
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ObjectCollection Items
{
get { return ((ComboBox)this).Items; }
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new object DataSource
{
get { return ((ComboBox)this).DataSource; }
Genero todas mis columnas en un DataGridView
subclasificado mediante programación. Sin embargo, Visual Studio 2008 sigue leyendo mi clase de constructor (que rellena un DataTable
con contenido vacío y lo vincula al DataGridView
) y genera código para las columnas en el método InitializeComponent
, en el proceso que establece AutoGenerateColumns
en false
.
Esto causa errores en la compilación de tiempo de diseño que solo se resuelven al acceder manualmente al código de diseño y al eliminar todas las referencias a estas columnas autogeneradas.
¿Cómo puedo detenerlo haciendo esto?
Yo he tratado:
- Haciendo el control ''Frozen''
- Establecer el objeto instanciado
DataGridView
protected
(sugerido en una publicación anterior que hace referencia a este sitio )
Parece que está agregando controles en el constructor. Tal vez agregue las columnas un poco más tarde, tal vez algo así como sobrescribir OnParentChanged
; entonces podrá verificar DesignMode
para que solo agregue las columnas durante la ejecución (no durante el diseño).
Hago esto a menudo en mis controles personalizados, si ajusta el código que no desea ejecutar en el diseñador en una verificación de DesignMode, debería solucionar sus problemas.
if (!DesignMode)
{
// Your code here
}
Mark tenía razón. El Diseñador mira al constructor para este comportamiento de autogeneración. Así es como lo solucioné.
Tomó el código que construye / vincula DataTable a DataGridView fuera del constructor y lo colocó en un método.
Usando el evento Load
en el formulario que contiene - que contiene múltiples DataGridView
s llama al método BindData()
en cada instancia,
List<Control> childControls = Misc.Misc.GetAllChildControls(this);
foreach (Control ctrl in childControls) {
if (ctrl is WorksheetGridView) {
WorksheetGridView wsgv = ctrl as WorksheetGridView;
wsgv.BindData();
}
}
donde GetAllChildControls
es un método en una clase de ayuda
internal static List<Control> GetAllChildControls(Control topControl)
{
List<Control> ctrlStore = new List<Control>();
ctrlStore.Add(topControl);
if (topControl.HasChildren)
{
foreach (Control ctrl in topControl.Controls)
{
ctrlStore.AddRange(GetAllChildControls(ctrl)); }
}
}
return ctrlStore;
}
Lo siento si esto es explícito, pero nunca quiero olvidar cómo hacerlo.
Me encontré con un problema similar a este, y estoy publicando mi solución aquí, ya que cuando escribí mi pregunta, esta fue la principal pregunta sugerida. Cada vez que compilé mi código, el diseñador agregaría cada una de las columnas en el origen de datos automáticamente (y la próxima vez que creara mi código aparecerían en la aplicación en ejecución) a pesar de que las columnas autogeneradas se establecieron en falso.
Eventualmente logré detenerlo dando a una de mis columnas el mismo nombre que tenía la columna generada automáticamente (mis columnas habían sido creadas originalmente antes de que la fuente de datos estuviera disponible).
La sugerencia de JaredPar funcionó para mí:
public partial class RefusjonsOppgjorGrid : DataGridView
{
public RefusjonsOppgjorGrid()
{
InitializeComponent();
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new DataGridViewColumnCollection Columns
{
get{ return base.Columns;}
}
}
Esta es una vieja pregunta ahora, pero sigue siendo un problema en 2014 con VS2013.
Tenía un DataGridView
con su DataSource
configurado en un BindingSource
que a su vez tenía otro BindingSource
como su DataSource
. Para resolver mi problema, no tuve que cambiar nada más que mover la asignación DataGridView.DataSource a una anulación OnControlCreate
en el formulario.
Dado que esto todavía parece ser una pregunta para algunos, incluyéndome a mí hasta hace unos días, pensé que publicaría mi solución, y la que estoy enseñando a los estudiantes en mis clases de ahora en adelante:
Primero, creo un objeto DataGridView
(DGV) y creo las columnas en la vista de diseño, tomando nota del nombre del objeto para la columna en particular.
Ahora, cuando quiero vincular datos de mi base de datos (SQL Server, para este código). Altere los objetos de columna y enlace cada columna directamente a los datos de DataTable
.
private void FillAddresses()
{
// erase any old data
if (AddrTable != null)
AddrTable.Clear();
else
AddrTable = new DataTable();
// switch-case for panel types that need an address
switch(PanelType)
{
case "Customer":
case "Customers":
case "Location":
case "Locations":
case "Employee":
case "Employees":
BuildStateColumnChoices();
SqlCommand sqlAddrCmd = new SqlCommand();
sqlAddrCmd.CommandText = "exec SecSchema.sp_GetAddress " + PanelType +
"," + ObjectID.ToString(); // Fill the DataTable with a stored procedure
sqlAddrCmd.Connection = DBConnection;
sqlAddrCmd.CommandType = CommandType.Text;
SqlDataAdapter sqlDA = new SqlDataAdapter(sqlAddrCmd);
try
{
sqlDA.Fill(AddrTable);
dgvAddresses.AutoGenerateColumns = false;
// Actually, you set both the DataSource and DataPropertyName properties to bind the data
dgvAddresses.DataSource = AddrTable;
// Note that the column parameters are using the name of the object from the designer.
// This differs from the column names.
// The DataProperty name is set to the column name returned from the Stored Procedure
dgvAddresses.Columns["colAddrType"].DataPropertyName = "Type";
dgvAddresses.Columns["collAddress"].DataPropertyName = "Address";
dgvAddresses.Columns["colAptNum"].DataPropertyName = "Apt#";
dgvAddresses.Columns["colCity"].DataPropertyName = "city";
dgvAddresses.Columns["colState"].DataPropertyName = "State";
dgvAddresses.Columns["colZIP"].DataPropertyName = "ZIP Code";
}
catch(Exception errUnk)
{
MessageBox.Show("Failed to load address data for panel type " +
PanelType + "..." + errUnk.Message, "Address error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
break;
}
}
Para el código anterior, DBConnection es una propiedad pública para el objeto del que tomé este código, que almacenó el objeto SqlConnection
. Además, colAddressType era una columna ComboBox. Los datos del DataTable
encuadernado solo pueden coincidir con la información que figura en el ComboBox. Del mismo modo, colState es una columna ComboBox, pero los valores predeterminados para este cuadro se agregan al consultar otra tabla que contiene todos los estados (en los Estados Unidos, para este ejemplo).
El punto aquí es que puede vincular los datos que desea incluir en un DGV creando las columnas en el momento del diseño, y luego vinculando sus datos directamente desde su DataTable a las columnas. Esto le permite tener cualquier tipo de columna que desee, en lugar de solo la columna de texto predeterminada que le otorga el mecanismo de enlace predeterminado.
Cabe señalar que, en este caso, DataTable es el resultado de un procedimiento almacenado y que la edición en este caso no es probable. Traté de usar una Vista así como una función almacenada; el primero tampoco permitió la edición (al menos, no es fácil ... sospecho que necesitaba una inserción antes del desencadenador en alguna parte, pero esa es una pregunta de la base de datos), mientras que la segunda no devolvería la tabla en función de algún problema con la dinámica generación de tablas
La respuesta de @JaredPar me ayudó a resolver esto, pero cualquier control que contuviera mi subclase DataGridView
agregaría las columnas cada vez que cambiara algo en el diseñador.
Quería mantener las columnas en el constructor para que se pudieran ver en el diseñador visual, así que tuve que deshabilitar el DataGridViewDesigner
estándar que mi subclase heredó de su base, es decir. Cambié el atributo Diseñador para mi clase ...
using System.Windows.Forms.Design;
[Designer(typeof(ControlDesigner))]
public class SpecificDataGridView : DataGridView
{
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new DataGridViewColumnCollection Columns
{
get { return base.Columns; }
}
...etc...
}
Significa que los diseñadores no pueden usar los "Elementos de edición" y otros en las tareas de DataGridViewDesigner y que no podían ajustar las propiedades de las columnas si así lo deseaban, pero para mis necesidades, eso no era particularmente útil por lo que era sin pérdida.
De todos modos, eso solucionó el problema y todavía significaba que las columnas eran visibles en el diseñador, que era mi objetivo principal aquí.
Solo pensé en compartir.
Vuelva a abrir el formulario en el diseñador de modo que las columnas se generen automáticamente, luego haga clic en DataGridView, seleccione Editar columnas, pase por cada columna ofensiva y establezca su propiedad ''Visible'' en False. Vuelva a guardar y cierre / vuelva a abrir el formulario para asegurarse de que ya no esté sucediendo. Esta fue la única solución no codificante que realmente funcionó para mí y no quería agregar código para resolver lo que es un problema de diseño de winforms.