CRUD con DevExpress ASPxGridView: combo para llaves foráneas y checkbox para 0/1

Qué vamos a lograr

Una página Articulos.aspx con una grilla que:

  • Lista, crea, edita y borra artículos (CRUD completo con SqlDataSource, sin escribir código de acceso a datos).
  • Muestra el impuesto con un selector (combo) que enseña el nombre (TAX_NOMBRE) en vez del TAX_ID.
  • Muestra el campo FAVORITO (entero 0/1) como checkbox.

Requisitos previos

  • ASP.NET WebForms (VB) con DevExpress 13.2 instalado.
  • Dos tablas en SQL Server:
CREATE TABLE Articulos (
ARTICULO_ID INT PRIMARY KEY,
NOMBRE VARCHAR(100),
NOMBRE_CORTO VARCHAR(50),
TAX_ID INT, -- llave foránea a Impuestos
PRECIO FLOAT,
MEDIDA VARCHAR(20),
FAVORITO INT -- 0 = no, 1 = sí
);
CREATE TABLE Impuestos (
TAX_ID INT PRIMARY KEY,
TAX_NOMBRE VARCHAR(50),
PORCENTAJE DECIMAL(5,2)
);

Paso 1 — Cadena de conexión y registro de DevExpress (Web.config)

En <connectionStrings>:

<add name="SPOSDBConnectionString"
connectionString="Data Source=localhost\sqlexpress;Initial Catalog=SPOSDB;Persist Security Info=True;User ID=usuario;Password=clave"
providerName="System.Data.SqlClient" />

Asegúrate de tener registrados los ensamblados de DevExpress en <system.web><compilation><assemblies> y el módulo ASPxHttpHandlerModule en <httpModules>/<system.webServer><modules> (esto normalmente lo agrega la plantilla de DevExpress al crear el proyecto).

Paso 2 — La página completa Articulos.aspx

Nota clave: arriba se registran dos namespaces con el prefijo dx (uno para el grid y otro para los editores, que es donde vive el combo/checkbox).

<%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/Site.Master" CodeBehind="Articulos.aspx.vb" Inherits="WebApplication2.Articulos" %>
<%@ Register Assembly="DevExpress.Web.v13.2, Version=13.2.12.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxGridView" TagPrefix="dx" %>
<%@ Register Assembly="DevExpress.Web.v13.2, Version=13.2.12.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxEditors" TagPrefix="dx" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<div class="container">
<div class="row">
<div class="col-md-12">
<dx:ASPxGridView runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource1"
EnableTheming="True" KeyFieldName="ARTICULO_ID" Theme="Aqua">
<Columns>
<dx:GridViewCommandColumn ShowDeleteButton="True" ShowEditButton="True" ShowNewButtonInHeader="True" VisibleIndex="0" />
<dx:GridViewDataTextColumn FieldName="ARTICULO_ID" ReadOnly="True" VisibleIndex="1" />
<dx:GridViewDataTextColumn FieldName="NOMBRE" VisibleIndex="2" />
<dx:GridViewDataTextColumn FieldName="NOMBRE_CORTO" VisibleIndex="3" />
<!-- Selector (combo) para la llave foránea TAX_ID -->
<dx:GridViewDataComboBoxColumn FieldName="TAX_ID" Caption="Impuesto" VisibleIndex="4">
<PropertiesComboBox DataSourceID="SqlDataSourceImpuestos"
TextField="TAX_NOMBRE" ValueField="TAX_ID" ValueType="System.Int32"
DropDownStyle="DropDownList" IncrementalFilteringMode="StartsWith">
</PropertiesComboBox>
</dx:GridViewDataComboBoxColumn>
<dx:GridViewDataTextColumn FieldName="PRECIO" VisibleIndex="5" />
<dx:GridViewDataTextColumn FieldName="MEDIDA" VisibleIndex="6" />
<!-- Checkbox para el entero 0/1 -->
<dx:GridViewDataCheckColumn FieldName="FAVORITO" Caption="Favorito" VisibleIndex="7">
<PropertiesCheckEdit ValueType="System.Int32" ValueChecked="1" ValueUnchecked="0" />
</dx:GridViewDataCheckColumn>
</Columns>
</dx:ASPxGridView>
<!-- Origen de datos principal: CRUD de Articulos -->
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:SPOSDBConnectionString %>"
SelectCommand="SELECT [ARTICULO_ID], [NOMBRE], [NOMBRE_CORTO], [TAX_ID], [PRECIO], [MEDIDA], [FAVORITO] FROM [Articulos]"
DeleteCommand="DELETE FROM [Articulos] WHERE [ARTICULO_ID] = @ARTICULO_ID"
InsertCommand="INSERT INTO [Articulos] ([ARTICULO_ID], [NOMBRE], [NOMBRE_CORTO], [TAX_ID], [PRECIO], [MEDIDA], [FAVORITO]) VALUES (@ARTICULO_ID, @NOMBRE, @NOMBRE_CORTO, @TAX_ID, @PRECIO, @MEDIDA, @FAVORITO)"
UpdateCommand="UPDATE [Articulos] SET [NOMBRE] = @NOMBRE, [NOMBRE_CORTO] = @NOMBRE_CORTO, [TAX_ID] = @TAX_ID, [PRECIO] = @PRECIO, [MEDIDA] = @MEDIDA, [FAVORITO] = @FAVORITO WHERE [ARTICULO_ID] = @ARTICULO_ID">
<DeleteParameters>
<asp:Parameter Name="ARTICULO_ID" Type="Int32" />
</DeleteParameters>
<InsertParameters>
<asp:Parameter Name="ARTICULO_ID" Type="Int32" />
<asp:Parameter Name="NOMBRE" Type="String" />
<asp:Parameter Name="NOMBRE_CORTO" Type="String" />
<asp:Parameter Name="TAX_ID" Type="Int32" />
<asp:Parameter Name="PRECIO" Type="Double" />
<asp:Parameter Name="MEDIDA" Type="String" />
<asp:Parameter Name="FAVORITO" Type="Int32" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="NOMBRE" Type="String" />
<asp:Parameter Name="NOMBRE_CORTO" Type="String" />
<asp:Parameter Name="TAX_ID" Type="Int32" />
<asp:Parameter Name="PRECIO" Type="Double" />
<asp:Parameter Name="MEDIDA" Type="String" />
<asp:Parameter Name="FAVORITO" Type="Int32" />
<asp:Parameter Name="ARTICULO_ID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
<!-- Origen de datos secundario: sólo para llenar el combo de impuestos -->
<asp:SqlDataSource ID="SqlDataSourceImpuestos" runat="server"
ConnectionString="<%$ ConnectionStrings:SPOSDBConnectionString %>"
SelectCommand="SELECT [TAX_ID], [TAX_NOMBRE], [PORCENTAJE] FROM [Impuestos] ORDER BY [TAX_NOMBRE]">
</asp:SqlDataSource>
</div>
</div>
</div>
</asp:Content>

El code-behind Articulos.aspx.vb queda vacío (todo lo resuelve el SqlDataSource):

Public Class Articulos
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
End Class

Cómo funciona cada truco

1) El combo para la llave foránea (GridViewDataComboBoxColumn)

  • ValueField="TAX_ID" → el valor real que se guarda en Articulos (el ID).
  • TextField="TAX_NOMBRE" → lo que ve el usuario (el nombre).
  • ValueType="System.Int32"imprescindible para que el valor entre correcto al parámetro @TAX_ID (Int32).
  • DropDownStyle="DropDownList" → obliga a elegir de la lista.
  • En modo lectura, la grilla traduce sola TAX_ID → TAX_NOMBRE.

2) El checkbox para 0/1 (GridViewDataCheckColumn)

  • Como el campo es entero (no bit), hay que decirle qué es "marcado" y "desmarcado":
    • ValueChecked="1", ValueUnchecked="0", ValueType="System.Int32".
  • Si hubiera NULL, el checkbox se ve gris (indeterminado); puedes agregar AllowGrayed="False".

Errores comunes

  • "Etiqueta de servidor 'dx:...' desconocida" → falta registrar el namespace correcto arriba con <%@ Register %>.
  • El combo guarda vacío o falla al actualizar → casi siempre es que falta ValueType="System.Int32".

Comentarios

Entradas más populares de este blog

Sacando aceleracion de un vehiculo en c++

Ejemplo de suma Pascal

Gráfica de Seno y Coseno en C++ | Código C++