Tutorial: Crear una aplicación de base de datos de clientes
En este tutorial se crea una aplicación sencilla para administrar una lista de clientes. Al hacerlo, se presentan una selección de conceptos básicos para aplicaciones empresariales en UWP. Aprenderá a:
- Implementar las operaciones Create, Read, Update y Delete en una base de datos SQL local.
- Agregar una cuadrícula de datos para mostrar y editar los datos de los clientes en la interfaz de usuario.
- Organizar los elementos de la interfaz de usuario juntos en un diseño de formulario básico.
El punto de partida de este tutorial es una aplicación de una sola página con una interfaz de usuario y funcionalidad mínimas, basada en una versión simplificada de la aplicación de ejemplo Base de datos de pedidos de clientes. Está escrita en C# y XAML, y esperamos que tenga conocimientos básicos sobre ambos lenguajes.
Requisitos previos
- Asegúrese de que tiene la versión más reciente de Visual Studio y el SDK de Windows
- Clonar o descargar el ejemplo del tutorial de base de datos del cliente
Después de clonar o descargar el repositorio, puede editar el proyecto abriendo CustomerDatabaseTutorial.sln con Visual Studio.
Nota:
Este tutorial se basa en el ejemplo de base de datos de pedidos de clientes que se ha actualizado recientemente para usar WinUI y el SDK de Aplicaciones para Windows. Hasta que se actualice este tutorial y el código, habrá diferencias entre los dos ejemplos.
Parte 1: Código de interés
Si ejecuta la aplicación inmediatamente después de abrirla, verá algunos botones en la parte superior de una pantalla en blanco. Aunque no es visible para usted, la aplicación ya incluye una base de datos de SQLite local aprovisionada con algunos clientes de prueba. Desde aquí, empezará implementando un control de interfaz de usuario para mostrar esos clientes y, a continuación, pasará a agregar operaciones en la base de datos. Antes de empezar, aquí está donde trabajará.
Vistas
CustomerListPage.xaml es la vista de la aplicación, que define la interfaz de usuario de una sola página de este tutorial. Cada vez que necesite agregar o cambiar un elemento visual en la interfaz de usuario, lo hará en este archivo. Este tutorial le guiará a través de la adición de estos elementos:
- RadDataGrid para mostrar y editar los clientes.
- StackPanel para establecer los valores iniciales de un nuevo cliente.
ViewModels
ViewModels\CustomerListPageViewModel.cs es donde se encuentra la lógica fundamental de la aplicación. Todas las acciones de usuario realizadas en la vista se pasarán a este archivo para su procesamiento. En este tutorial, agregará código nuevo e implementará los métodos siguientes:
- CreateNewCustomerAsync, que inicializa un nuevo objeto CustomerViewModel.
- DeleteNewCustomerAsync, que quita un nuevo cliente antes de que se muestre en la interfaz de usuario.
- DeleteAndUpdateAsync, que controla la lógica del botón eliminar.
- GetCustomerListAsync, que recupera una lista de clientes de la base de datos.
- SaveInitialChangesAsync, que agrega la información de un nuevo cliente a la base de datos.
- UpdateCustomersAsync, que actualiza la interfaz de usuario para reflejar los clientes agregados o eliminados.
CustomerViewModel es un contenedor para la información de un cliente, que realiza un seguimiento de si se ha modificado recientemente o no. No tendrá que agregar nada a esta clase, pero parte del código que agregará en otro lugar hará referencia a ella.
Para obtener más información sobre cómo se construye el ejemplo, consulte la información general sobre la estructura de la aplicación.
Parte 2: Agregar DataGrid
Antes de empezar a operar con los datos de los clientes, deberá agregar un control de interfaz de usuario para mostrar esos clientes. Para ello, usaremos un control RadDataGrid de terceros creado previamente. El paquete NuGet Telerik.UI.for.UniversalWindowsPlatform ya está incluido en este proyecto. Vamos a agregar la cuadrícula al proyecto.
Abra Views\CustomerListPage.xaml desde el Explorador de soluciones. Agregue la siguiente línea de código dentro de la etiqueta Page para declarar una asignación al espacio de nombres Telerik que contiene la cuadrícula de datos.
xmlns:telerikGrid="using:Telerik.UI.Xaml.Controls.Grid"
Debajo de CommandBar, dentro del elemento RelativePanel principal de la vista, agregue un control RadDataGrid, con algunas opciones de configuración básicas:
<Grid x:Name="CustomerListRoot" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <RelativePanel> <CommandBar x:Name="mainCommandBar" HorizontalAlignment="Stretch" Background="AliceBlue"> <!--CommandBar content--> </CommandBar> <telerikGrid:RadDataGrid x:Name="DataGrid" BorderThickness="0" ColumnDataOperationsMode="Flyout" GridLinesVisibility="None" GroupPanelPosition="Left" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.Below="mainCommandBar" /> </RelativePanel> </Grid>
Ha agregado la cuadrícula de datos, pero necesita que se muestren los datos. Agregue las siguientes líneas de código:
ItemsSource="{x:Bind ViewModel.Customers}" UserEditMode="Inline"
Ahora que ha definido un origen de datos que se va a mostrar, RadDataGrid controlará la mayoría de la lógica de la interfaz de usuario. Sin embargo, si ejecuta el proyecto, todavía no verá ningún dato en pantalla. Esto se debe a que ViewModel aún no lo está cargando.
Parte 3: Leer los clientes
Cuando se inicializa, ViewModels\CustomerListPageViewModel.cs llama al método GetCustomerListAsync. Ese método debe recuperar los datos del cliente de prueba de la base de datos de SQLite que se incluye en el tutorial.
En ViewModels\CustomerListPageViewModel.cs, actualice el método GetCustomerListAsync con este código:
public async Task GetCustomerListAsync() { var customers = await App.Repository.Customers.GetAsync(); if (customers == null) { return; } await DispatcherHelper.ExecuteOnUIThreadAsync(() => { Customers.Clear(); foreach (var c in customers) { Customers.Add(new CustomerViewModel(c)); } }); }
Se llama al método GetCustomerListAsync cuando se carga ViewModel, pero antes de este paso, no hizo nada. Aquí, hemos agregado una llamada al método GetAsync en Repository/SqlCustomerRepository. Esto le permite ponerse en contacto con el repositorio para recuperar una colección enumerable de objetos de cliente. A continuación, los analiza en objetos individuales, antes de agregarlos a su ObservableCollection interna para que se puedan mostrar y editar.
Ejecutar la aplicación: ahora verá la cuadrícula de datos que muestra la lista de clientes.
Parte 4: Editar los clientes
Puede editar las entradas de la cuadrícula de datos haciendo doble clic en ellas, pero debe asegurarse de que los cambios que realice en la interfaz de usuario también se realicen en la colección de clientes en el código subyacente. Esto significa que tendrá que implementar el enlace de datos bidireccional. Si desea obtener más información al respecto, consulte nuestra introducción al enlace de datos.
En primer lugar, declare que ViewModels\CustomerListPageViewModel.cs implementa la interfaz INotifyPropertyChanged:
public class CustomerListPageViewModel : INotifyPropertyChanged
A continuación, en el cuerpo principal de la clase, agregue el siguiente evento y método:
public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
El método OnPropertyChanged facilita que los establecedores generen el evento PropertyChanged, que es necesario para el enlace de datos bidireccional.
Actualice el establecedor para SelectedCustomer con esta llamada de función:
public CustomerViewModel SelectedCustomer { get => _selectedCustomer; set { if (_selectedCustomer != value) { _selectedCustomer = value; OnPropertyChanged(); } } }
En Views\CustomerListPage.xaml, agregue la propiedad SelectedCustomer a la cuadrícula de datos.
SelectedItem="{x:Bind ViewModel.SelectedCustomer, Mode=TwoWay}"
Esto asocia la selección del usuario en la cuadrícula de datos con el objeto Customer correspondiente en el código subyacente. El modo de enlace bidireccional permite que los cambios realizados en la interfaz de usuario se reflejen en ese objeto.
Ejecute la aplicación. Ahora puede ver los clientes mostrados en la cuadrícula y realizar cambios en los datos subyacentes a través de la interfaz de usuario.
Parte 5: Actualizar los clientes
Ahora que puede ver y editar los clientes, deberá poder insertar los cambios en la base de datos y extraer las actualizaciones realizadas por otros usuarios.
Vuelva a ViewModels\CustomerListPageViewModel.cs y vaya al método UpdateCustomersAsync. Actualícelo con este código para insertar cambios en la base de datos y recuperar cualquier información nueva:
public async Task UpdateCustomersAsync() { foreach (var modifiedCustomer in Customers .Where(x => x.IsModified).Select(x => x.Model)) { await App.Repository.Customers.UpsertAsync(modifiedCustomer); } await GetCustomerListAsync(); }
Este código utiliza la propiedad IsModified de ViewModels\CustomerViewModel.cs, que se actualiza automáticamente cada vez que se cambia el cliente. Esto le permite evitar llamadas innecesarias y solo insertar cambios de clientes actualizados en la base de datos.
Parte 6: Crear un nuevo cliente
Agregar un nuevo cliente presenta un desafío, ya que el cliente aparecerá como una fila en blanco si lo agrega a la interfaz de usuario antes de proporcionar valores para sus propiedades. No es un problema, pero aquí vamos a facilitar la configuración de los valores iniciales de un cliente. En este tutorial, agregaremos un panel contraíble sencillo, pero si tuviera más información para agregar podría crear una página independiente para este propósito.
Actualización del código subyacente
Agregue un nuevo campo privado y una propiedad pública a ViewModels\CustomerListPageViewModel.cs. Se usará para controlar si el panel está visible o no.
private bool _addingNewCustomer = false; public bool AddingNewCustomer { get => _addingNewCustomer; set { if (_addingNewCustomer != value) { _addingNewCustomer = value; OnPropertyChanged(); } } }
Agregue una nueva propiedad pública a ViewModel, un inverso del valor de AddingNewCustomer. Se usará para deshabilitar los botones de la barra de comandos normales cuando el panel esté visible.
public bool EnableCommandBar => !AddingNewCustomer;
Ahora necesitará una manera de mostrar el panel contraíble y crear un cliente para editarlo.
Agregue una nueva propiedad pública y privada a ViewModel para contener el cliente recién creado.
private CustomerViewModel _newCustomer; public CustomerViewModel NewCustomer { get => _newCustomer; set { if (_newCustomer != value) { _newCustomer = value; OnPropertyChanged(); } } }
Actualice el método CreateNewCustomerAsync para crear un nuevo cliente, agréguelo al repositorio y establézcalo como cliente seleccionado:
public async Task CreateNewCustomerAsync() { CustomerViewModel newCustomer = new CustomerViewModel(new Models.Customer()); NewCustomer = newCustomer; await App.Repository.Customers.UpsertAsync(NewCustomer.Model); AddingNewCustomer = true; }
Actualice el método SaveInitialChangesAsync para agregar un cliente recién actualice la interfaz de usuario y cierre el panel.
public async Task SaveInitialChangesAsync() { await App.Repository.Customers.UpsertAsync(NewCustomer.Model); await UpdateCustomersAsync(); AddingNewCustomer = false; }
Agregue la siguiente línea de código como línea final en el establecedor para AddNewCustomer:
OnPropertyChanged(nameof(EnableCommandBar));
Esto garantizará que EnableCommandBar se actualice automáticamente cada vez que se cambie AddingNewCustomer.
Actualización de la interfaz de usuario
Vuelva a Views\CustomerListPage.xaml y agregue un StackPanel con las siguientes propiedades entre CommandBar y la cuadrícula de datos:
<StackPanel x:Name="newCustomerPanel" Orientation="Horizontal" x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}" RelativePanel.Below="mainCommandBar"> </StackPanel>
El atributo x:Load garantiza que este panel solo aparezca cuando se agrega un nuevo cliente.
Realice el siguiente cambio en la posición de la cuadrícula de datos para asegurarse de que se mueve hacia abajo cuando aparezca el nuevo panel:
RelativePanel.Below="newCustomerPanel"
Actualice el panel de pila con cuatro controles TextBox. Se enlazarán a las propiedades individuales del nuevo cliente y le permitirán editar sus valores antes de agregarlos a la cuadrícula de datos.
<StackPanel x:Name="newCustomerPanel" Orientation="Horizontal" x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}" RelativePanel.Below="mainCommandBar"> <TextBox Header="First name" PlaceholderText="First" Margin="8,8,16,8" MinWidth="120" Text="{x:Bind ViewModel.NewCustomer.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBox Header="Last name" PlaceholderText="Last" Margin="0,8,16,8" MinWidth="120" Text="{x:Bind ViewModel.NewCustomer.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBox Header="Address" PlaceholderText="1234 Address St, Redmond WA 00000" Margin="0,8,16,8" MinWidth="280" Text="{x:Bind ViewModel.NewCustomer.Address, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBox Header="Company" PlaceholderText="Company" Margin="0,8,16,8" MinWidth="120" Text="{x:Bind ViewModel.NewCustomer.Company, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </StackPanel>
Agregue un botón simple al nuevo panel de pila para guardar el cliente recién creado:
<StackPanel> <!--Text boxes from step 3--> <AppBarButton x:Name="SaveNewCustomer" Click="{x:Bind ViewModel.SaveInitialChangesAsync}" Icon="Save"/> </StackPanel>
Actualice CommandBar, por lo que los botones normales de creación, eliminación y actualización se deshabilitan cuando el panel de pila está visible:
<CommandBar x:Name="mainCommandBar" HorizontalAlignment="Stretch" IsEnabled="{x:Bind ViewModel.EnableCommandBar, Mode=OneWay}" Background="AliceBlue"> <!--App bar buttons--> </CommandBar>
Ejecute la aplicación. Ahora puede crear un cliente y escribir sus datos en el panel de pila.
Parte 7: Eliminar un cliente
La eliminación de un cliente es la operación básica final que debe implementar. Al eliminar un cliente seleccionado en la cuadrícula de datos, querrá llamar inmediatamente a UpdateCustomersAsync para actualizar la interfaz de usuario. Sin embargo, no es necesario llamar a ese método si va a eliminar un cliente que acaba de crear.
Vaya a ViewModels\CustomerListPageViewModel.cs y actualice el método DeleteAndUpdateAsync:
public async void DeleteAndUpdateAsync() { if (SelectedCustomer != null) { await App.Repository.Customers.DeleteAsync(_selectedCustomer.Model.Id); } await UpdateCustomersAsync(); }
En Views\CustomerListPage.xaml, actualice el panel de pila para agregar un nuevo cliente para que contenga un segundo botón:
<StackPanel> <!--Text boxes for adding a new customer--> <AppBarButton x:Name="DeleteNewCustomer" Click="{x:Bind ViewModel.DeleteNewCustomerAsync}" Icon="Cancel"/> <AppBarButton x:Name="SaveNewCustomer" Click="{x:Bind ViewModel.SaveInitialChangesAsync}" Icon="Save"/> </StackPanel>
En ViewModels\CustomerListPageViewModel.cs, actualice el método DeleteNewCustomerAsync para eliminar el nuevo cliente:
public async Task DeleteNewCustomerAsync() { if (NewCustomer != null) { await App.Repository.Customers.DeleteAsync(_newCustomer.Model.Id); AddingNewCustomer = false; } }
Ejecute la aplicación. Ahora puede eliminar clientes, ya sea dentro de la cuadrícula de datos o en el panel de pila.
Conclusión
Felicidades. Una vez hecho todo esto, la aplicación ahora tiene una amplia gama de operaciones de base de datos locales. Puede crear, leer, actualizar y eliminar clientes dentro de la interfaz de usuario, y estos cambios se guardan en la base de datos y se conservarán en distintos inicios de la aplicación.
Ahora que ha terminado, tenga en cuenta lo siguiente:
- Si aún no lo ha hecho, consulte la información general sobre la estructura de la aplicación para obtener más información sobre por qué la aplicación se ha compilado así.
- Explore el ejemplo completo de base de datos de pedidos de clientes para ver la aplicación en la que se basa este tutorial.
O si le apetece un reto, puede seguir adelante...
Ir más lejos: Conectarse a una base de datos remota
Hemos proporcionado un tutorial paso a paso sobre cómo implementar estas llamadas en una base de datos de SQLite local. Pero, ¿qué ocurre si desea usar una base de datos remota?
Si quiere probarlo, necesitará su propia cuenta de Azure Active Directory (AAD) y la capacidad de hospedar su propio origen de datos.
Deberá agregar autenticación, funciones para controlar las llamadas REST y, a continuación, crear una base de datos remota con la que interactuar. Hay código en el ejemplo completo de base de datos de pedidos de clientes que puede consultar para cada operación necesaria.
Opciones y configuración
Los pasos necesarios para conectarse a su propia base de datos remota se describen en el archivo Léame del ejemplo. Deberá hacer lo siguiente:
- Proporcione el identificador de cliente de la cuenta de Azure para Constants.cs.
- Proporcione la dirección URL de la base de datos remota para Constants.cs.
- Proporcione la cadena de conexión de base de datos para Constants.cs.
- Asocie la aplicación con Microsoft Store.
- Copie el proyecto de servicio en la aplicación e impleméntelo en Azure.
Autenticación
Deberá crear un botón para iniciar una secuencia de autenticación y un elemento emergente o una página independiente para recopilar la información de un usuario. Una vez que lo haya creado, deberá proporcionar código que solicite la información de un usuario y lo use para adquirir un token de acceso. El ejemplo de base de datos de pedidos de clientes ajusta las llamadas de Microsoft Graph con la biblioteca WebAccountManager para adquirir un token y controlar la autenticación en una cuenta de AAD.
- La lógica de autenticación se implementa en AuthenticationViewModel.cs.
- El proceso de autenticación se muestra en el control AuthenticationControl.xaml personalizado.
Llamadas de REST
No tendrá que modificar ninguno de los códigos que hemos agregado en este tutorial para implementar llamadas REST. En su lugar, necesitará hacer lo siguiente:
- Cree nuevas implementaciones de las interfaces ICustomerRepository e ITutorialRepository, implementando el mismo conjunto de funciones a través de REST en lugar de SQLite. Tendrá que serializar y deserializar JSON y puede encapsular las llamadas REST en una clase HttpHelper independiente si es necesario. Consulte el ejemplo completo para obtener información específica.
- En App.xaml.cs, cree una nueva función para inicializar el repositorio REST y llámela en lugar de SqliteDatabase cuando se inicialice la aplicación. De nuevo, consulte el ejemplo completo.
Una vez completados los tres pasos, debería poder autenticarse en la cuenta de AAD a través de la aplicación. Las llamadas REST a la base de datos remota reemplazarán las llamadas de SQLite locales, pero la experiencia del usuario debe ser la misma. Si todavía quiere ir más lejos, puede agregar una página de configuración para permitir que el usuario cambie dinámicamente entre las dos.