ASP.NET AJAX Data Grid: Estados de casilla de verificación habilitados y deshabilitados
¿Está comprobado o no del todo? Las casillas de verificación de varios estados están en el menú hoy. Lo que, por supuesto, plantea la pregunta "¿No es WebDataGrid ya compatible con las columnas de casilla de verificación listas para usar?".
¿Está comprobado o no del todo? Las casillas de verificación de varios estados están en el menú hoy. Lo que, por supuesto, plantea la pregunta "¿No es WebDataGrid ya compatible con las columnas de casilla de verificación listas para usar?".
Sí, admite un campo de casilla de verificación de tres estados, pero hay casos en los que es posible que necesite un poco más de flexibilidad. Como se nos ha recordado en nuestra plataforma de comentarios de ideas de productos, tener más estados de casilla de verificación con variaciones habilitadas y deshabilitadas es algo de lo que los propios usuarios pueden beneficiarse directamente. Esto se debe en parte a que el comportamiento de edición de la cuadrícula trata los campos de casillas de verificación de forma masiva (como en toda la columna) y tal vez incluso porque no hay una señal visual, las casillas de verificación de la columna no se pueden editar. Entonces, si desea más que las casillas de verificación estándar de tres estados que se pueden configurar para cada fila, siga leyendo. Basándonos en los comentarios que recibimos, el equipo ha preparado una solución y yo también he añadido mi propio giro, y quiero compartirlo con vosotros.
Configuración
Aquí se asumen algunas cosas: desea mostrar una cuadrícula de datos con una columna de casilla de verificación vinculada o sin enlazar, pero también desea usar el comportamiento Edición y controlar si la casilla de verificación de cada fila se puede editar en función de una condición o de sus otras columnas de datos. De esta manera, de tres estados, en combinación con habilitado y deshabilitado, pasamos a seis y eso es algo que es posible que deba almacenar en más de una columna. Dependiendo de sus datos y caso, esa columna adicional se puede usar como bandera meteorológica o no, la casilla de verificación debe estar activa o todo el estado. La implementación de algo como esto puede ser muy diferente, por lo que es posible que se requiera un poco de adaptación, pero intentaré señalar los conceptos básicos que son reutilizables y marcar las características opcionales en el código de demostración.
Basics
La idea detrás de agregar un estado deshabilitado es bastante inteligente: reemplace la imagen de la casilla de verificación con la imagen inactiva respectiva y realice una verificación en tiempo de ejecución de esas imágenes para evitar la edición. De este modo, se obtiene el control sobre la indicación visual, pero también sobre los detalles de la imagen que se pueden utilizar para la detección. Por lo tanto, necesita 3 imágenes, junto con un objeto de configuración para el lado del cliente con rutas y valores para ellas y mapeo entre la casilla de verificación y sus celdas de estado ocultas.
Eventos de cliente que se van a gestionar:
- Inicializar: vaya a través de las casillas de verificación que tienen un estado adicional y aplique la apariencia habilitada / deshabilitada
- Asa Corrección 's CellValueChanging para evitar que se deshabilite la edición. Además, tenga en cuenta que el evento se desencadena cuando se usa la API, por lo que si desea poder cambiar los valores mediante programación del lado del cliente, es posible que deba usar el método"_set_value_internal" método en su lugar.
- Si usa casillas de verificación no enlazadas con un cuadro de encabezado, también debe controlar HeaderCheckBoxClicked para establecer el estado adecuado y quizás el valor.
Puede usar campos enlazados de sus datos actuales, agregar otros nuevos para hacerlo si no están disponibles, usar campos no vinculados con el único propósito de mantener marcas o incluso habilitar y deshabilitar casillas de verificación basadas en la lógica ejecutada en el cliente.
External Flag Approach
Esto utiliza la funcionalidad estándar de la casilla de verificación junto con la aplicación de estados editables basados en una marca, que puede ser otra columna de datos, predeterminada por la lógica del servidor y transferida como campo (no) enlazado o completamente basada en la lógica del lado del cliente. La implementación realmente depende de usted, usaré otra columna bool como parte de los datos, y dado que tengo dos columnas de casilla de verificación, los dos últimos campos llevan banderas deshabilitadas para ellas:
<ig:WebDataGrid ID="WebDataGrid1" runat="server" Height="350px" Width="100%" AutoGenerateColumns="False" DataKeyFields="ID" StyleSetName="IG">
<Columns>
<ig:BoundDataField DataFieldName="ID" Key="ID">
<Header Text="ID" />
</ig:BoundDataField>
<ig:BoundDataField DataFieldName="CheckBoxState" Key="CheckBoxState">
<Header Text="CheckBox State" />
</ig:BoundDataField>
<ig:BoundCheckBoxField DataFieldName="BoundCheckBox" Key="BoundCheckBox" DataType="System.Boolean">
<Header Text="Bound CheckBox" />
</ig:BoundCheckBoxField>
<ig:BoundCheckBoxField Key="DisableBoundCheckBox">
<Header Text="Check to disable corresponding BoundCheckBox" />
</ig:BoundCheckBoxField>
<ig:UnboundCheckBoxField Key="UnboundCheckBox" HeaderCheckBoxMode="TriState">
<Header Text="UnboundCheckBox"/>
</ig:UnboundCheckBoxField>
<ig:UnboundCheckBoxField Key="DisableUnboundCheckBox" HeaderCheckBoxMode="TriState">
<Header Text="Check to disable corresponding UnboundCheckBox" />
</ig:UnboundCheckBoxField>
<%-- Hidden columns to store the states for the CheckBoxFields --%>
<ig:BoundDataField Key="BoundCheckBoxDisabled" Hidden="true" DataType="System.Boolean">
<Header Text="Bound CheckBox Disabled?" />
</ig:BoundDataField>
<ig:BoundDataField Key="UnboundCheckBoxDisabled" Hidden="true" DataType="System.Boolean">
<Header Text="Unbound CheckBox Disabled?" />
</ig:BoundDataField>
</Columns>
<ClientEvents Initialize="WebDataGrid_Grid_Initialize" HeaderCheckBoxClicked="WebDataGrid_Grid_HeaderCheckboxClicked" />
<Behaviors>
<ig:EditingCore>
<EditingClientEvents CellValueChanging="WebDataGrid_Editing_CellValueChanging" CellValueChanged="WebDataGrid_Editing_CellValueChanged" />
<Behaviors>
<ig:CellEditing>
<ColumnSettings>
<ig:EditingColumnSetting ColumnKey="ID" ReadOnly="True" />
</ColumnSettings>
<EditModeActions MouseClick="Single" EnableOnKeyPress="true"/>
</ig:CellEditing>
</Behaviors>
</ig:EditingCore>
</Behaviors>
</ig:WebDataGrid>
Se establece el estado inicial basado en los valores de esos y las imágenes de casilla de verificación deshabilitadas reemplazan los valores predeterminados cuando sea necesario:
var styleName = "<%= this.WebDataGrid1.StyleSetName %>" || "Default";
var clientSettings = {
"true": { src: "images/" + styleName + "/ig_checkbox_disabled_on.gif", value: true, chkState: 1 },
"false": {src: "images/" + styleName + "/ig_checkbox_disabled_off.gif", value: false, chkState: 0 },
"null": { src: "images/" + styleName + "/ig_checkbox_disabled_partial.gif", value: null, chkState: 2 },
"columns": {2: 6, 4: 7}
};
function WebDataGrid_Grid_Initialize(sender, eventArgs) {
// Set initial enabled / disabled state for all checkboxes
try {
var rows = sender.get_rows();
var rowCount = rows.get_length();
for (var i = 0; i < rowCount; i++) {
var row = rows.get_row(i);
for (columnIndex in clientSettings["columns"]){
// Set the correct enabled/disabled states:
var checkBoxCell = row.get_cell(columnIndex);
var hiddenStateCell = row.get_cell(clientSettings["columns"][columnIndex]);
var isDisabled = hiddenStateCell.get_value();
SetCheckState(checkBoxCell, isDisabled, hiddenStateCell);
}
}
}
catch (ex) { }
}
function SetCheckState(cell, isDisabled, checkStateCell) {
// Set Enabled or disabled state to a cell (adjust image and title/alt) and store in secondary cell.
try {
if (isDisabled === isCellDisabled(cell)) return;
var checkBoxElem = cell.get_element().getElementsByTagName("img").item(0); //get checkbox image
var chkStates = clientSettings[String(cell.get_value())]; //get state info
if (!chkStates) return;
if (isDisabled === true) {
// Set the disabled values of src and title for the checkbox
checkBoxElem.src = chkStates.src;
checkBoxElem.title = "Disabled " + checkBoxElem.title;
checkBoxElem.alt = "Disabled " + checkBoxElem.alt;
}
else {
// re-set value to restore state
checkBoxElem.src = "";
//use _internal to force setting the same value
cell._set_value_internal(chkStates.value, chkStates.chkState);
}
checkStateCell.set_value(isDisabled); // Store the new checkbox state value in the corresponding hidden checkbox
}
catch (ex) { }
}
function isCellDisabled(cell) {
var checkBoxElem = cell.get_element().getElementsByTagName("img").item(0);
return checkBoxElem && checkBoxElem.src.toLowerCase().indexOf("disabled") >= 0;
}
Evitar ediciones en las casillas de verificación deshabilitadas y, en el caso de los campos no enlazados, conserve el estado cuando se utilice el cuadro de encabezado:
function WebDataGrid_Editing_CellValueChanging(sender, eventArgs) {
// Prevent edit actions on disabled checkboxes
try {
var currCell = eventArgs.get_cell();
if (isCellDisabled(currCell))
eventArgs.set_cancel(true); // cancel event to prevent value change
}
catch (ex) { }
}
function WebDataGrid_Grid_HeaderCheckboxClicked(sender, eventArgs) {
var columnIndex = eventArgs.get_column().get_index();
var rows = sender.get_rows();
var rowCount = rows.get_length();
// When the header of the "UnboundCheckBox" column is clicked,
// set the check states for all while maintaining enabled/disabled states
if (clientSettings["columns"][columnIndex]) {
for (var i = 0; i < rowCount; i++) {
var row = rows.get_row(i);
var unboundCheckBoxCell = row.get_cell(columnIndex);
var hiddenUnboundCheckBoxCell = unboundCheckBoxCell.get_row().get_cell(clientSettings["columns"][columnIndex]);
var unboundCheckBoxCellVal = hiddenUnboundCheckBoxCell.get_value();
SetCheckState(unboundCheckBoxCell, unboundCheckBoxCellVal, hiddenUnboundCheckBoxCell);
}
}
}
Por supuesto, mantener el estado de los campos no enlazados es tan opcional como el propio cuadro de encabezado: es una cuestión de lo que pueda necesitar. En este punto, puede usar la función SetCheckState para alternar el estado y puede proporcionar al usuario varias formas de hacerlo si es necesario (consulte el código de demostración que maneja los cambios de valor de los campos de casilla de verificación estándar vecinos).

P.D. Si desea una mejor legibilidad para los pares de columnas en la configuración del cliente, puede almacenar claves en su lugar y usar el método "get_cellByColumnKey" donde elegí los índices, porque sabe que ambos en el servidor y el método de clave lo usará para encontrar el índice de todos modos.
Enfoque todo en uno
Este es el indicado si necesita mantener todo en una sola celda de datos. El enfoque todo en uno opta por una sola columna de datos que contiene el estado completo en la casilla de verificación como una cadena, tal como se ve en las capturas de pantalla: "EnabledOn", "EnabledOff", etc. Por lo tanto, una vez más necesita dos columnas, una casilla de verificación y otra oculta que lleve el estado real. Un conjunto similar de controladores de eventos para proporcionar el aspecto y el comportamiento del lado del cliente y tendrá una solución igual de funcional.
El marcado de la cuadrícula, con variaciones para los campos obligatorios enlazados y no enlazados, es esencialmente el mismo, al igual que la "desactivación" de las casillas de verificación mediante la comprobación de su origen de imagen y la cancelación de la edición y el manejo de eventos de inicialización. La principal diferencia proviene del hecho de que setting state trata y guarda los valores de cadena completos:
// Sets the enabled/disabled state on the bound/unbound checkbox in the given cell
function SetCheckState(cell, chkState, checkStateCell) {
try {
var checkState = chkState? chkState.replace("Enabled", "Disabled"): "";
var checkBoxElem = cell.get_element().getElementsByTagName("img").item(0);
var chkStates = checkStates[checkState];
if (!chkStates) return;
// Get the default values of src and title for checkbox in its enabled state
var enabledSrc = null, enabledTitle = null;
if (chkState && chkState.indexOf("Enabled") >= 0) {
enabledSrc = "ig_res/Default/" + chkStates.src.replace("disabled_", "");
enabledTitle = chkState.replace("Enabled", "").replace("On", "Checked").replace("Off", "Unchecked");
}
cell.set_value(chkStates.value, chkStates.chkState);
checkBoxElem.src = enabledSrc? enabledSrc : chkStates.src;
checkBoxElem.title = enabledTitle ? enabledTitle : chkStates.title;
checkBoxElem.alt = enabledTitle ? enabledTitle : chkStates.alt;
checkStateCell.set_value(chkState); // Store the new checkbox state value in the corresponding hidden checkbox
}
catch (ex) { }
}

Bonus round
Por supuesto, cuando menciono que necesita dos columnas para este enfoque nuevamente, me refiero a que no siempre será efectivo vincular una columna de casilla de verificación a valores de cadena como "DisabledOn". Sin embargo, eso no significa que no puedas hacerlo. Con la interfaz IBooleanConverter, puede vincular el campo de casilla de verificación (esto excluye naturalmente las opciones no vinculadas) y, de hecho, también facilita el código de cliente requerido porque no necesitará la columna oculta adicional.
public class CheckboxConverter : IBooleanConverter {
public object DefaultFalseValue {
get {
return "EnabledOff";
}
}
public object DefaultTrueValue {
get {
return "EnabledOn";
}
}
public bool IsFalse(object value) {
return value.ToString().Contains("Off");
}
public bool IsTrue(object value) {
return value.ToString().Contains("On");
}
}
Una ventaja del manejo del convertidor es que cuando las casillas de verificación editables establecerán los valores predeterminados de verdadero / falso cuando el usuario interactúe con ellos y usarán las reglas para que coincidan con marcado o desmarcado y cuando nada coincida (léase: "EnabledPartial") también establecerá la casilla de verificación en estado parcial. ¡Qué conveniente!
Options, Options, Options
Supongo que eso es exactamente lo que este blog puede brindarte: 3 formas de lograr la funcionalidad de casilla de verificación de estado múltiple habilitado y deshabilitado. Tanto si desea dos columnas booleanas que proporcionen un estado combinado como un enfoque de una sola columna con un par de columnas ocultas y de presentación o campos de enlace a través de un convertidor, todas las versiones producen un comportamiento similar con diferentes cantidades de esfuerzo y limitaciones. ¡Depende de usted decidir cuál se adapta mejor a sus requisitos y reutilizar la mayor cantidad posible del código de demostración!
Hablando de código, aquí están los sitios de demostración ASP.NET:
- Dos columnas booleanas: una casilla de verificación + una para las banderas
- Columna de datos única con versiones de columna oculta y convertidor
Abra como sitio web desde Visual Studio o WebMatrix y necesitará instalar Infragistics ASP.NET (es posible que necesite ajustes de versión de referencia) que puede obtener desde aquí.
Me encantaría escuchar tus opiniones, así que deja un comentario a continuación o envíame un mensaje@DamyanPetev.
Y como siempre, puedes seguirnos en Twitter@ Infragisticsy mantenerte en contacto enFacebook,Google+yLinkedIn.