Introducción al desarrollo de Windows Mobile

En el mundo actual de la comida rápida, los coches rápidos y la gratificación instantánea, la gente espera estar en contacto en todo momento.

Nos hemos condicionado a estar en contacto con las empresas, los amigos y las familias. Debido a este deseo de información instantánea, tenemos Internet, teléfonos móviles, Wi-Fi, reproductores de MP3 y reproductores de DVD. A medida que el equipo necesario para impulsar esta sed se ha ido haciendo cada vez más pequeño, nos encontramos buscando sustitutos portátiles para nuestros voluminosos ordenadores de sobremesa.

Este artículo le guiará en el apasionante mundo del desarrollo móvil para que pueda aprovechar una oportunidad cada vez mayor de suministrar software a este floreciente mercado.

Cómo empezar

Actualmente existen dos opciones para producir software móvil utilizando un sistema operativo Windows: XP con ActiveSync y Vista con una nueva interfaz basada en la tecnología ActiveSync denominada Windows Mobile Device Center (WMDC).

En el reciente número de CoDe Focus sobre desarrollo de PC móviles (2007, volumen 4, número 2), el artículo de Nick Landry titulado «Windows Vista Mobility: Why Should You Care?» ofrece una buena revisión y un tutorial sobre el uso de WMDC con Vista. Si vas a utilizar WMDC, definitivamente querrás leer este artículo.

Si utilizas Vista, descarga WMDC desde el sitio de Microsoft; si no, descarga ActiveSync para utilizarlo con XP. Los demás requisitos de software no dependen del sistema operativo. Al instalar Visual Studio 2008, también se instalan .NET Compact Framework y SQL Server Mobile Edition. Visual Studio 2008 es necesario para utilizar la última versión de los distintos marcos. Si tiene previsto desarrollar para versiones anteriores de Compact Framework, puede utilizar Visual Studio 2008 o 2005.

The Compact Framework

The Compact Framework es el vehículo para el desarrollo móvil. ¿En qué se diferencia Compact Framework de la versión completa? Para empezar, Microsoft ha eliminado la mayoría de las sobrecargas de métodos y funcionalidades no esenciales. Como resultado, Compact Framework ocupa mucho menos espacio. Destilar el framework normal a un tamaño fácilmente instalable en un dispositivo con memoria y capacidad de disco limitadas no debe de haber sido tarea fácil. Compact Framework proporciona casi todo lo necesario para desarrollar para teléfonos inteligentes y ordenadores de bolsillo. Sin embargo, Compact Framework no proporciona soporte para:

  • Despliegue con un solo clic
  • Remoting
  • Printing
  • Web Forms
  • Archivos de configuración
  • Serialización binaria

Puede reemplazar fácilmente la mayoría de las funcionalidades que faltan con su código personalizado o con soluciones disponibles de terceros proveedores de soluciones.

SQL Server Mobile Edition (SQLme)

Aunque SQLme es un subconjunto de SQL Server normal, que funciona tanto con SQL Server 2005/2008 como con las versiones Express de cada producto, la mayor parte de la funcionalidad necesaria está ahí. Puede utilizar la consola de administración de SQL Server para gestionar su base de datos móvil de SQL Server en el escritorio o en la PPC a través de una conexión directa.

Hay algunas limitaciones al utilizar SQLme:

  • No hay procedimientos almacenados
  • No hay consultas por lotes
  • Diseño de tablas limitadas

La falta de procedimientos almacenados no es un gran problema a superar. Es fácil simular procedimientos almacenados usando TableAdapters. Cree tantos métodos en el TableAdapter como sea necesario. Cuando necesito hacer una llamada de datos, puedo referirme al nombre del método en lugar de a un procedimiento almacenado. Si decido no utilizar TableAdapters, puedo simplemente añadir métodos a mi capa de datos para realizar la misma tarea

La capacidad de consulta por lotes tampoco es un gran problema con los datos desconectados. Usted no está haciendo cantidades masivas de munición de datos o la extracción en la plataforma móvil. La mayoría de las operaciones básicas de datos en una plataforma móvil son la recuperación de datos para su visualización y actualización. Dado que estas solicitudes de recuperación son a través de una capa de datos, no hace ninguna diferencia si los comandos se procesan juntos o uno a la vez.

El diseño de la tabla limitada no es un problema real tampoco. Lo más frustrante de usar el editor de tablas en el estudio de gestión es que no puedes mover las columnas en tu diseño sin borrarlas y rehacerlas en orden. Asegúrate de que tu diseño es el que quieres antes de crear varias tablas. Aparte de la fácil manipulación del diseño de la tabla, el resto es como la versión normal, por lo que tiene una amplia gama de tipos de datos para apoyar sus necesidades.

Datos móviles

Los datos móviles difieren de las aplicaciones de escritorio principalmente por:

  • Factor de forma
  • Restricciones de memoria
  • Velocidad del procesador
  • Ancho de banda
  • Naturaleza desconectada

El factor de forma es probablemente la restricción más seria en el mundo del desarrollo móvil. Los tamaños de pantalla de los móviles van de 2 x 3 pulgadas a 5 x 7 pulgadas; las resoluciones, de 240 x 320 píxeles a 640 x 480 píxeles; y las formas, de cuadradas a rectángulos verticales u horizontales.

Al diseñar el uso de la pantalla para una aplicación móvil, hay que tener en cuenta las restricciones de espacio y planificar en consecuencia. Hay una serie de cuestiones que debe afrontar al diseñar formularios para el dispositivo móvil. Voy a abordar estos en detalle en la sección que trata de controles compactos más adelante en este artículo.

Las restricciones de memoria son otro factor de diseño. En los dispositivos móviles, la memoria se mide en megabytes, no en gigabytes. Aunque puedes utilizar minitarjetas para aumentar el espacio de almacenamiento, no aumentan la cantidad de memoria disponible para los programas. Debido a la limitación de recursos, no conviene almacenar muchos datos en la memoria y dejar pocos para el uso del sistema. Los sistemas operativos móviles cerrarán los programas que se ejecutan en segundo plano para proporcionar recursos a la aplicación en primer plano.

La velocidad de los procesadores requiere ser consciente del tiempo que tardan ciertas operaciones o de la duración de las consultas en la base de datos. Los fabricantes de dispositivos son conscientes de la necesidad de velocidad y están presionando a los fabricantes de chips para que lancen procesadores cada vez más rápidos. Los PPC que saldrán a la venta a finales de este año utilizarán los últimos procesadores de 700 MHz.

El ancho de banda es menor que el de los sistemas cableados o las redes internas, por lo que el acceso a los datos, en el mundo actual, es más lento que el de los ordenadores de sobremesa y los portátiles. Se están haciendo grandes avances en este campo, pero todavía está en la vanguardia y habrá que esperar hasta que la infraestructura se ponga al día con la tecnología.

La naturaleza desconectada de los datos presenta algunos desafíos. SQLme ofrece varias formas de gestionar los datos en el dispositivo móvil: Acceso Remoto a Datos, Replicación de Fusión y un nuevo servicio llamado Sincronizador de Bases de Datos de Microsoft Access. Estas capacidades le permiten mover los datos a/desde el dispositivo móvil; sin embargo, estos servicios no son compatibles con las ediciones de SQL Server Express.

Con todo, es bastante simple trabajar alrededor de estas limitaciones mediante el uso de un buen diseño simple y mecanismos de recuperación de datos eficientes.

Integración de Visual Studio

El desarrollo de Compact Framework como Windows Forms o Web Forms se integra directamente en Visual Studio. Con este acoplamiento, puede desarrollar su aplicación, controlar los emuladores, probar la replicación de SQL, escribir pruebas unitarias y colocar el dispositivo para probar la sincronización mediante WMDC o ActiveSync.

Tiene dos opciones a la hora de escribir/probar su aplicación móvil:

Desarrollar con el dispositivo real es una práctica común cuando quiere probar la velocidad del programa, la facilidad de uso físico, etc. Sin embargo, esto puede ser una propuesta costosa si quieres probar muchos dispositivos.

Los emuladores son dispositivos virtuales construidos en la misma plataforma de hardware que el dispositivo original. Los emuladores facilitan mucho el desarrollo para muchos dispositivos diferentes con distintos factores de forma y capacidades. Microsoft proporciona una serie de emuladores, tanto con el SDK de Windows Mobile 5.0 como con el SDK de Windows Mobile 6, que le permiten probar múltiples factores de forma y requisitos de los dispositivos.

La mayoría de los fabricantes de tecnología móvil actuales también proporcionan emuladores para sus dispositivos con el fin de ayudarle en su labor de desarrollo. Por lo tanto, si necesita un emulador específico, el Treo 750 por ejemplo, puede descargarlo desde el sitio web del fabricante.

Desarrollo móvil

Los proyectos de aplicaciones móviles se crean de la misma manera que las aplicaciones de escritorio normales: En el menú Archivo, seleccione Nuevo y, a continuación, Proyecto.

En Visual Studio 2008, seleccione Proyecto de dispositivo inteligente (Figura 1). Se indica el nombre del proyecto en la parte inferior y se establece la edición de Compact Framework de destino mediante la lista desplegable de la parte superior de la pantalla. Al hacer clic en Aceptar en esta pantalla se accede a un formulario posterior en el que se elige el tipo de proyecto de destino (Figura 2). Visual Studio creará entonces su solución y añadirá un programa y un formulario por defecto.

Figura 1: Selección del proyecto para dispositivos inteligentes en Visual Studio 2008.
Figura 1: Selección del proyecto para dispositivos inteligentes en Visual Studio 2008.
Figura 2: Selección del tipo de proyecto para el desarrollo de dispositivos móviles.
Figura 2: Selección del tipo de proyecto para el desarrollo de dispositivos móviles.

Desea renombrar el formulario y el programa para darles nombres significativos. Ahora puede construir su solución como lo haría normalmente con una aplicación de escritorio. A medida que necesite bibliotecas de clases u otros formularios, simplemente haga clic con el botón derecho en la solución o el proyecto y añada el elemento deseado.

La mejor práctica para el diseño de aplicaciones normales es utilizar un enfoque de tres niveles: una capa de interfaz de usuario, una capa de negocio y una capa de datos. Es una práctica común en el desarrollo de aplicaciones separar estas funcionalidades específicas de la aplicación en clases individuales. Si mi intención fuera utilizar la aplicación móvil como un consumidor de servicios web o utilizar las mismas clases de back-end que las aplicaciones web o de PC, el enfoque de tres niveles todavía se aplicaría.

Sin embargo, en la aplicación de pedidos móviles que acompaña a este artículo, sólo estoy utilizando dos niveles. Dado que voy a utilizar conjuntos de datos fuertemente tipados y los adaptadores de tablas incluidos con ellos, no tiene sentido tener otra capa de datos con llamadas a métodos duplicados sólo para separar la funcionalidad. El programa de pedidos móviles tendrá una capa de interfaz de usuario y una capa de negocio.

La base de datos

Puedes crear tu base de datos compacta utilizando Visual Studio o SQL Server. Para este ejemplo, crearás las tablas que necesitas utilizando la funcionalidad incorporada de Visual Studio:

!(https://codemag.com/Article/Image/0807071/Baird_Figure 3.tif)

!(https://codemag.com/Article/Image/0807071/Baird_Figure 4.tif)

Ahora que tienes la base de datos creada, puedes empezar a crear las tablas que necesitas para la aplicación haciendo clic con el botón derecho en la nueva conexión de datos y eligiendo «Crear tabla». Para la aplicación de pedidos móviles, he creado estas tablas: cliente, pedido, orderitem, inventario, proveedor y fabricante.

Con la estructura de la base de datos en su lugar, puede crear conjuntos de datos fuertemente tipados arrastrando cada tabla desde el explorador del servidor al diseñador de conjuntos de datos. El diseñador creará entonces todo el código necesario para usted cuando lo cierre.

Windows Forms vs. Mobile Forms

Mucho del desarrollo de formularios móviles es el mismo que el de Windows Forms; sin embargo, hay algunas diferencias claras. Estas diferencias incluyen:

  • Enlace de datos
  • Rejilla de datos/controladores personalizados
  • Eventos
  • Entrada de datos

Con los formularios de Windows, el enlace de datos es la mejor práctica aceptada; con los formularios móviles, el enlace manual es a veces mejor. La vinculación manual es más rápida que la vinculación de datos. Dado que sólo se trata de un puñado de controles en cualquier formulario, el esfuerzo necesario para vincular los controles a los datos es más problemático de lo que vale. La vinculación de datos tiene sentido si necesitas:

  • Vinculación maestra/detallada
  • Navegación
  • Administrador de divisas/Fuente de vinculación

Aquí tienes un ejemplo de cómo uso la vinculación manual en el proyecto adjunto. Para rellenar los controles:

private void FillOrderHeaderControls( OrderDataSet.OrderRow dr){ this.txtCustomer.Text = dr.CustomerName; this.dtgOrderDate.Value = dr.OrderDate;}private void FillOrderItemControls( OrderItemDataSet.OrderItemRow dr){ this.txtManPartNo = _dr.ManPartNo; this.cboInventory.SelectedValue =_dr.fkInventory; this.txtQuantity.Text = (string)dr.quantity; this.txtPrice.Text = _dr.price; _dtItem.AddOrderItemRow(_dr);}

Para recoger los valores de los controles a la fila:

private void FillOrderHeaderRow() { _drOrder = _dtOrder.NewOrderRow(); _drOrder.fkCustomer = _cBiz.GetCustomerKey( this.txtCustomer.Text); _drOrder.OrderDate = this.dtgOrderDate.Value; _dtOrder.AddOrderRow(_drOrder);}private void FillOrderItemsRow(){ _drItem = _dtItem.NewOrderItemRow(); _drItem.ManPartNo = _iBiz.GetManPartNo(value); _drItem.fkOrder = 0; _drItem.fkInventory = this.GetInventoryKey (this.cboInventory.Text); _drItem.Description = this.cboInventory.Text.Trim(); _drItem.quantity = (int)this.txtQuantity.Text; _drItem.price = (decimal)this.txtPrice.Text _dtItem.AddOrderItemRow(_drItem);}

Una de las preguntas más comunes en el foro de Compact Framework trata de añadir controles personalizados a las columnas de la rejilla. Fuera de la caja, el control DataGrid no soporta columnas personalizadas sin algo de trabajo extra a diferencia del control DataGrid del framework regular.

Con el lanzamiento de .NET CF 2.0 SP1, el equipo expuso el método Paint en la columna Grid, que permite la creación de controles personalizados. Debido al número de peticiones de ayuda con ello, crearon un paquete disponible para su descarga que empaqueta una serie de controles para ti, incluyendo el ComboBox, el CheckBbox, y un DateTimePicker. Puedes descargarlo desde:

blogs.msdn.com/netcfteam/attachment/583542.ashx

Una vez referenciado en tu proyecto, puedes incluir columnas personalizadas con facilidad:

//TextBox ColumnDataGridCustomTextBoxColumn colOrdNo = new DataGridCustomTextBoxColumn();colOrdNo.Owner = this.grdSearch;colOrdNo.HeaderText = "No";colOrdNo.MappingName = "OrderNo";colOrdNo.Alignment = HorizontalAlignment.Left;//CheckBox ColumDataGridCustomCheckBoxColumn colTaxable = new DataGridCustomCheckBoxColumn();colTaxable.Owner = this.grdSearch;colTaxable.HeaderText = "Taxable";colTaxable.MappingName = "Taxable";colTaxable.Alignment = HorizontalAlignment.Center;

Los dispositivos móviles no permiten introducir datos fácilmente en los controles de los formularios. La entrada de texto se realiza mediante un mini teclado QWERTY integrado en el hardware o mediante un teclado de software emergente llamado SIP (panel de entrada de software). En los smartphones más antiguos sin teclado de hardware, hay que pulsar los números del teclado para seleccionar el texto. En cualquier caso, la entrada de texto es difícil, consume tiempo y es tediosa.

Un diseñador de formularios móviles debe limitar la cantidad de entrada de datos necesaria mediante el uso de controles planificados con criterio. Utilice listas desplegables con las opciones más comunes, casillas de verificación y listas para limitar la cantidad de escritura necesaria.

Los eventos son otra diferencia clara. En un típico formulario de Windows, hay más de 75 eventos de los que se puede elegir; mientras que un formulario móvil tiene 23. Un botón normal tiene 60 eventos; un botón CF tiene 11.

Debido a esta disparidad en los eventos, tendrá que pensar más en el flujo del programa y en la creación y diseño de sus formularios y proyectos móviles que en sus aplicaciones Windows Forms.

Creación del formulario de pedido

La funcionalidad del formulario de pedido mostrará las principales técnicas a la hora de crear formularios para aplicaciones móviles. Cuando se diseñan formularios para móviles, hay que recordar que el espacio del formulario es mínimo y que los cambios en el factor de forma pueden afectar al diseño y a la entrada de datos. Este problema se resuelve utilizando un TabControl o panel en cada formulario como contenedor de los objetos que contiene. Con un TabControl, puede ampliar la disponibilidad de espacio en pantalla añadiendo etiquetas y más controles según sea necesario.

El formulario de pedido del siguiente ejemplo tendrá la siguiente funcionalidad:

  • Buscar un pedido.
  • Ver un pedido específico.
  • Editar el pedido seleccionado.
  • Borrar el pedido seleccionado.
  • Añadir un nuevo pedido.
  • Para crear el diseño del formulario, arrastré un TabControl desde la ToolBox, y luego añadí varios controles a las TabPages para mostrar lo que quería. Cada formulario cuando se añade al proyecto tiene un control MainMenu vacío añadido a él. Para crear sus acciones de menú, simplemente haga clic en la barra de menú (Figura 5) y escriba. Puedes añadir tantos elementos de menú horizontal y verticalmente como necesites.
  •  Figure 6 and Figure 7 show the completed order form with its TabControl in place and the MainMenu items added.

!(https://codemag.com/Article/Image/0807071/Baird_Figure 5.tif)

!(https://codemag.com/Article/Image/0807071/Baird_Figure 6.tif)

!(https://codemag.com/Article/Image/0807071/Baird_Figure 7.tif)

Para buscar un determinado pedido, utilizarás la clave de cliente y un rango de fechas. Yo he puesto como rango de fechas por defecto el periodo de cien años que va de 1950 a 2050. El código para la búsqueda es el siguiente (en este ejemplo, _rowNumber se establece en un método que determina el número de fila de la fila seleccionada del DataGrid en un método de golpeo de la cuadrícula):

private void SearchMenuItem_Click( object sender, EventArgs e){ OrderBiz biz = new OrderBiz(); _dtOrder = biz.Find( this.cboCustomer.Text.Trim(), this.dtgStartDate.Value, this.dtgEndDate.Value); this.grdSearch.Select(_rowNumber); if (_dtOrder.Rows.Count > 0) { this.ViewMenuItem.Enabled = true; this.DeleteMenuItem.Enabled = true; }}

En este ejemplo de código, se hace una llamada al objeto de negocio del pedido para realizar la búsqueda y devolver un conjunto de datos fuertemente tipado que contiene los pedidos coincidentes. El método Find() del objeto de negocio se muestra aquí:

public OrderDataSet.OrderDataTable Find( string customerName, DateTime startDate, DateTime endDate){ OrderDataSet.OrderDataTable dt = new OrderDataSet.OrderDataTable(); OrderTableAdapter ta = new OrderTableAdapter(); if (customerName.Equals("ANY")) { customerName = string.Empty; } ta.FillBy(dt, startDate, endDate, "%"+customerName+"%"); return dt;}

La rejilla del formulario principal muestra los pedidos devueltos por la búsqueda. Al seleccionar un elemento de esta rejilla y pulsar el elemento de menú Ver, el pedido seleccionado y sus elementos de pedido se mostrarán en el modo de vista. El modo de visualización muestra el subtotal, los impuestos y el total del pedido, lo que requiere una instancia del objeto de negocio inventario además de los objetos de negocio pedido y elemento de pedido (Listado 1 y Listado 2 respectivamente).

Otro elemento a considerar es la entrada de datos en sus formularios. Si su dispositivo de destino admite tanto un teclado QWERTY de hardware como un SIP, debe preocuparse de que el SIP cubra los cuadros de texto cuando esté activado, impidiendo que se introduzca texto en los campos ocultos. En este caso, necesitas atrapar un evento y redimensionar tu TabControl para que no se cubran los campos.

El SIP incluye una propiedad llamada VisibleDesktop, que te permite saber cuánto espacio real es visible una vez que el SIP está abierto. Si es necesario, se añadirán barras de desplazamiento al TabControl para poder introducir texto en todos los campos disponibles. Este es el código:

private void inputPanel_EnabledChanged( object sender, EventArgs e){ if (inputPanel.Enabled) { //get the height of the TabControl _originalHeight = this.tcTab.Height; //adjust the TabControl for the SIP's space this.tcTab.Height = inputPanel.VisibleDesktop.Height; } else { this.tcTab.Height = _originalHeight; this.tcTab.Dock = DockStyle.Fill; }}

Ejecución y depuración del código

Usando Visual Studio, tienes dos opciones para configurar el dispositivo de destino para el despliegue. La primera es establecer el dispositivo de destino activo en la página de propiedades de su proyecto principal y la segunda opción es utilizar la lista desplegable de la barra de herramientas de dispositivos para seleccionar el dispositivo de destino o el emulador.

Si su código compila, comienza la implementación en el emulador/dispositivo de destino. Los CABs necesarios se transfieren al dispositivo de destino y se ejecutan para instalar las DLL que necesita su aplicación. Si estás utilizando un emulador, el despliegue de estos CABs es un proceso lento. Para evitar la espera cada vez que compila y despliega su aplicación, debe guardar el estado del emulador eligiendo Guardar estado en el menú Archivo o cerrando el formulario y respondiendo afirmativamente al cuadro de diálogo resultante.

Si establece puntos de interrupción en su código, puede detener la ejecución del programa en el emulador/dispositivo de destino y recorrer el código como en una aplicación de escritorio. Sin embargo, existen algunas limitaciones: Editar y Continuar no está soportado y no hay visualizadores DataSet, por lo que no se puede mirar el estado de los datos en un momento dado. Puede utilizar QuickWatch para visualizar el objeto y profundizar en la jerarquía de objetos para ver las colecciones de columnas y filas.

Empaquetando el código para su distribución

Una vez que haya terminado su código y esté satisfecho con su funcionalidad, estará listo para crear el CAB de distribución. Hay un proyecto especial disponible en la página Otros Proyectos/Configuración y Despliegue en el asistente de Nuevos Proyectos. Hay un par de pasos necesarios para empaquetar tu aplicación como un archivo CAB para su despliegue:

Cuando añades la salida principal al proyecto CAB, Visual Studio determina las dependencias necesarias por ti y las añade a tu proyecto automáticamente. Si se necesita algún archivo adicional, puede añadirlo manualmente. Debe añadir una referencia a la base de datos compacta que ha creado. Dado que las dependencias se han añadido ahora, puede terminar el proyecto de despliegue:

Esto completa la creación del proyecto de despliegue. Construya el proyecto como cualquier otro proyecto y la salida será su paquete de aplicación CAB.

Puede añadir iconos de programa y entradas de registro utilizando el proyecto CAB. Para una explicación más detallada que cubre este proceso de despliegue, consulte el artículo en: http://msdn2.microsoft.com/en-us/library/zcebx8f8(VS.90).aspx

Uno de los requisitos habituales para desplegar sus aplicaciones es empaquetar varios CAB en un paquete. Esto incluiría el CAB de su aplicación, el CAB de .NET Compact Framework, el CAB de SQLme y cualquier otro que requiera su programa. Dado que ha incluido todos los CAB necesarios, la instalación del programa puede realizarse sin errores. Todos los programas necesarios se instalan automáticamente antes de instalar su aplicación. Esto requiere un gran esfuerzo para empaquetar correctamente; sin embargo, hay una solución relativamente indolora: Pocket PC Installer que está disponible en: http://www.pocketpctoolkit.com.

Este económico programa, dirigido por un asistente, merece la pena. Incluye opciones para la mayoría de las características del instalador, incluidos los acuerdos de licencia y las imágenes de fondo. El instalador se crea simplemente arrastrando y soltando los archivos en la pantalla del listado de archivos (Figura 8).

(https://codemag.com/Article/Image/0807071/Baird_Figure 8.tif)

La mayor ventaja de este programa es que, una vez compilados los archivos de instalación, se han creado dos archivos ejecutables: un ejecutable para PC que se copia en el mismo y, desde allí, en un dispositivo conectado, y un segundo ejecutable para PPC que se copia directamente en el dispositivo.

Conclusión

El desarrollo de Compact Framework tiene un potencial de crecimiento explosivo. Estimaciones conservadoras indican que hay más de dos mil millones de teléfonos móviles en todo el mundo. Muchos ciudadanos de países del tercer mundo no pueden permitirse ni tendrán nunca un ordenador de sobremesa, pero utilizarán sus teléfonos móviles para acceder a Internet. Al emplear las ideas y técnicas de este artículo usted puede llegar a ser competente en el desarrollo para los mercados móviles y aprovechar esta oportunidad de crecimiento.

using System;using System.Data;using System.Linq;using System.Collections.Generic;using System.Text;using Quay.MobileOrders.DataSets;using Quay.MobileOrders.DataSets.OrderDataSetTableAdapters;namespace Quay.MobileOrders.Business{ public class OrderBiz { public OrderBiz() { } /// <summary> /// Has Changes /// are there any changes to the data? /// </summary> /// <returns>True/False</returns> public bool HasChanges(OrderDataSet.OrderDataTable dt) { bool retVal = false; DataTable dtChanged = dt.GetChanges(); if (dtChanged != null && dtChanged.Rows.Count > 0) { retVal = true; } return retVal; } /// <summary> /// Find /// returns all orders matching the search criteria. /// </summary> /// <param name="customerName">Customer name</param> /// <param name="startDate">Order start date</param> /// <param name="endDate">Order end date</param> /// <returns>Order Table</returns> public OrderDataSet.OrderDataTable Find(string customerName, DateTime startDate, DateTime endDate) { OrderDataSet.OrderDataTable dt = new OrderDataSet.OrderDataTable(); OrderTableAdapter ta = new OrderTableAdapter(); if (customerName.Equals("ANY")) { customerName = string.Empty; } ta.FillBy(dt, startDate, endDate, "%"+customerName+"%"); return dt; } /// <summary> /// Insert new order /// returns the newly added key. /// </summary> /// <param name="dr">data row</param> /// <returns>primary key of new record</returns> public int InsertNewOrder(OrderDataSet.OrderRow dr) { OrderTableAdapter ta = new OrderTableAdapter(); return (int)ta.InsertOrderRecord(dr.fkCustomer, dr.OrderDate); } /// <summary> /// Get Inserted key /// return the last key assigned by the insert clause /// </summary> /// <returns>order id</returns> public long GetInsertedKey() { OrderTableAdapter ta = new OrderTableAdapter(); return (long)ta.GetInsertedKey(); } /// <summary> /// Update order table /// </summary> /// <param name="dt">datatable to update</param> /// <returns>number of records updated</returns> public int UpdateOrderTable(OrderDataSet.OrderDataTable dt) { OrderTableAdapter ta = new OrderTableAdapter(); return ta.Update(dt); } /// <summary> /// Get Order by Order Key /// </summary> /// <param name="orderKey">Order key</param> /// <returns>Order Table</returns> public OrderDataSet.OrderDataTable GetOrderByOrderKey(long orderKey) { OrderTableAdapter ta = new OrderTableAdapter(); return ta.GetOrderByOrderKey(orderKey); } }}

Lista 2: OrderItemBiz-el objeto de negocio del artículo de la orden

using System;using System.Data;using System.Linq;using System.Collections.Generic;using System.Text;using Quay.MobileOrders.DataSets;using Quay.MobileOrders.DataSets.OrderItemDataSetTableAdapters;namespace Quay.MobileOrders.Business{ public class OrderItemBiz { public OrderItemBiz() { } /// <summary> /// Has Changes /// are there any changes to the data? /// </summary> /// <returns></returns> public bool HasChanges(OrderItemDataSet. OrderItemDataTable dt) { bool retVal = false; DataTable dtChanged = dt.GetChanges(); if (dtChanged != null && dtChanged.Rows.Count > 0) { retVal = true; } return retVal; } /// <summary> /// Get Order Item By Order Key /// </summary> /// <param name="orderKey">Order Key</param> /// <returns>Order Item table</returns> public OrderItemDataSet.OrderItemDataTable GetOrderItemByOrderKey(long orderKey) { OrderItemTableAdapter ta = new OrderItemTableAdapter(); return ta.GetOrderItemByOrderKey(orderKey); } /// <summary> /// Update OrderItem Table /// </summary> /// <param name="dt">Order Item DataTable</param> /// <returns>number of rows updated</returns> public int UpdateOrderItemTable( OrderItemDataSet.OrderItemDataTable dt) { OrderItemTableAdapter ta = new OrderItemTableAdapter(); return ta.Update(dt); } /// <summary> /// Get Order Subtotal /// Returns the subtotal of all items in a given order /// </summary> /// <param name="dt">Order Item DataTable</param> /// <returns>Subtotal for the order</returns> public decimal GetOrderSubTotal( OrderItemDataSet.OrderItemDataTable dt) { decimal subtotal = 0.00M; foreach (OrderItemDataSet.OrderItemRow dr in dt.Rows) { if (!dr.RowState.Equals(DataRowState.Deleted) || !dr.RowState.Equals(DataRowState.Detached)) { subtotal += (dr.quantity * (decimal)dr.price); } } return subtotal; } /// <summary> /// Get Order Tax /// Returns the tax applied to the subtotal of /// all items in a given order. /// </summary> /// <param name="subtotal">Order SubTotal</param> /// <returns>Tax for the order</returns> public decimal GetTax(decimal subtotal) { decimal tax = 0.075M; return ((decimal)subtotal) * ((decimal)tax); } /// <summary> /// Delete items /// </summary> /// <param name="orderKey"></param> public void DeleteItemByItemKey(long orderItemKey) { OrderItemTableAdapter ta = new OrderItemTableAdapter(); ta.DeleteItemByItemKey(orderItemKey); } /// <summary> /// Delete items /// </summary> /// <param name="orderKey"></param> public void DeleteItemsByOrderKey(long orderKey) { OrderItemTableAdapter ta = new OrderItemTableAdapter(); ta.DeleteItemsByOrderKey(orderKey); } }}

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *