Ir al contenido principal

Xamarin.Forms - Tabbed Page con SQLite - Parte 1

Hola nuevamente a todos, espero estén todos muy bien; hoy nos encontramos en la necesidad de desplazaron en diferentes secciones estando en la misma pantalla sin salirnos de la misma y que cada sección se comporte de manera independiente teniendo su propio diseño e información. Para lo cual Xamarin.Forms nos ofrece un tipo de página llamada: TabbedPage. 

Este post o artículo es parte de la aplicación DÍAbetes que se viene elaborando, hoy aprenderemos a implementar TabbedPage en ella.

Todas las pruebas se viene realizando en un equipo móvil físico con Sistema Operativo Android, esto no restringe el uso de emuladores, además recordarles que sólo se viene implementado por ahora los ejemplos prácticos para la plataforma de Android.

Requisitos:
Microsoft Visual Studio Community 2019.
Xamarin.Froms - XAML.
SQLite - Gestión de datos local.

¿Qué son los TabbedPage? 
Página que contiene diferentes pestañas o secciones (otras paginas entre sí) que hacen posible la navegación entre ellas en relación a la misma pantalla.

Nuestra necesidad es definir 3 secciones:
De las cuales especificamos los atributos o elementos que contendrán cada sección.

Cuenta (datos de la cuenta del usuario como el correo, nombre de la cuenta, password y activo - en relación al estado del usuario).

Info (información de usuario como nombres, apellidos, fecha de nacimiento, teléfono celular, tipo de persona y datos del médico tratante como el teléfono y el e-mail).

Config (cuenta las opciones de autorización de visualización de password, notificar cambio de password, habilitar envío de reporte a médico tratante).

Clases creadas:
El proyecto donde se implementa es la de AppDIAbetes; en las clases DataBase.cs, TaskExtensions.cs se mantiene las mismas instrucciones ya definidas (recordar que son instrucciones para la generación y conexión a la base de datos).

En la clase UserDB.cs se agregaron las instrucciones equivales al CRUD y se creó una nueva tarea de tipo list con un parámetro de entrada (Task<List<User>> userFillEmail(string strEmail)); en la clase User.cs se agregaron nuevos atributos.

Diseño de Interfaz:
En el sub directorio Views\Options agregaremos nuevos elementos: 1 elemento de tipo de Página con Pestañas (TabPagePeople.xaml), así mismo agregamos 3 elementos de tipo de Pagina de Contenido (TabPageAccount.xaml, TabPageInfo.xaml y TabPageConfig.xaml).

Consideración:
La pagina con pestañas o secciones (TabPagePeople.xaml) es el encargado de refrenciar o instanciar el TabbedPage que se rellene únicamente con el NavigationPage y ContentPage, esto ayuda a garantizar una experiencia de usuario único y coherente en el desplazamiento de cada pagina y es aplicado para todas las plataformas.

Además, para nuestro caso se importo la class en referencia (xmlns:local="clr-namespace:AppDIAbetes.Views.Options") al TabbedPage, esto se debe porque nuestro Página con Pestañas se encuentran en el sub directorio Views\Options. Así mismo se hace referencias a las de tipo de Pagina de Contenido (TabPageAccount, TabPageInfo y TabPageConfig).

XAML completo del archivo TabPagePeople.xaml.

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:AppDIAbetes.Views.Options"
             mc:Ignorable="d"
             x:Class="AppDIAbetes.Views.Options.TabPagePeople">
    <local:TabPageAccount />
    <local:TabPageInfo />
    <local:TabPageConfig />
</TabbedPage>

Para los de tipo de Pagina de Contenido agregaremos los siguientes atributos XAML en tag <ContentPage … los que está sombreado de color plomo ... (varia el contenido según la pagina):

             x:Class="AppDIAbetes.Views.Options.PaginaContenido"
             Title="Titulo de la cuenta"
             IconImageSource="UnaImagen.png"

             BackgroundColor="#FFFFFF"

XAML incluye los elementos y demás atributos en relación al archivo TabPageAccount.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="AppDIAbetes.Views.Options.TabPageAccount"
             Title="Cuenta"
             IconImageSource="UserAccount32.png"
             BackgroundColor="#FFFFFF">
    <ContentPage.Content>
        <AbsoluteLayout BackgroundColor="White" Margin="5,0,5,5">
            <FlexLayout IsVisible="True" JustifyContent="SpaceEvenly" Direction="Column" AlignItems="Center" Margin="30,0,30,0" >
                <Label x:Name="labelId" Text="" IsVisible="False" TextColor="Blue" FontSize="12" BackgroundColor="Transparent" FlexLayout.AlignSelf="End"/>               
                <Entry x:Name="entryEmail" Text="{Binding email}" Placeholder="Email" Keyboard="Email" FontSize="Small" FlexLayout.AlignSelf="Stretch" HorizontalOptions="CenterAndExpand" TextColor="Black" IsEnabled="False" />
                <Entry x:Name="entryName" Text="{Binding name}" Placeholder="Nombre de la cuenta" Keyboard="Text" MaxLength="10" FontSize="Small" FlexLayout.AlignSelf="Stretch" HorizontalOptions="CenterAndExpand" TextColor="Black"/>
                <Entry x:Name="entryPassword" Text="{Binding password}" Placeholder="Contraseña" Keyboard="Text" MaxLength="12" IsPassword="True" FontSize="Small" FlexLayout.AlignSelf="Stretch" HorizontalOptions="CenterAndExpand" TextColor="Black"/>
                <Entry x:Name="entryConfPassword" Text="{Binding password}" Placeholder="Confirmar Contraseña" MaxLength="12" IsPassword="True" FontSize="Small" FlexLayout.AlignSelf="Stretch"  HorizontalOptions="CenterAndExpand" TextColor="Black"/>
                <Label x:Name="warningPassword" Text="" IsVisible="False" TextColor="Blue" FontSize="12" BackgroundColor="Transparent" FlexLayout.AlignSelf="End"/>
                <Label Text="Activo" FontSize="Small" FlexLayout.AlignSelf="Start"/>
                <Switch x:Name="valActive" IsToggled="{Binding active}" FlexLayout.AlignSelf="Start" />
                <Button x:Name="cuentaEdit" Clicked="cuentaEdit_Clicked" FontSize="Medium" TextColor="White" BorderColor="Black" BackgroundColor="#6fb7ff"  CornerRadius="5" FlexLayout.AlignSelf="Stretch"  HorizontalOptions="CenterAndExpand" Text="Actualizar"></Button>
            </FlexLayout>
        </AbsoluteLayout>
    </ContentPage.Content>  
</ContentPage>

Implementar CodeBehind:
Como se mencionó en la clase UserDB.cs se creó una nueva tarea de tipo list con un parámetro de entrada (Task<List<User>> userFillEmail(string strEmail))

        public Task<List<User>> userFillEmail(string strEmail)
        {
            return Database.QueryAsync<User>("Select * from User Where email=?", strEmail);

        }

Acerca de los demás métodos y tareas existente en la clase UserDB.cs puede revisar el articulo de Xamarin.Forms - CRUD con SQLite

Seguidamente en la clase User.cs se agregaron nuevos atributos, ahora nuestra clase debe estar conformado de la siguiente manera:

using SQLite;
using System;

namespace AppDIAbetes.Models
{
    public class User
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string email { get; set; }
        public string name { get; set; }
        [MaxLength(8)]
        public string password { get; set; }
        public bool active { get; set; }
        public string image { get; set; }
        public DateTime regDate { get; set; }
        public DateTime updDate { get; set; }
    }
}

Se agregaron los atributos de regDate, updDate y se retiro el atributo phone además de cambiar la longitud máximo del atributo password.

Para finalizar implementaremos el CodeBehind de nuestra página de contenido TabPageAccount.xaml.cs para lo cual te sugiero que considerar los siguiente puntos:

1. Revisar el artículo de Xamarin.Forms - Administrar sesión de usuario
2. Seguir la indicaciones de cada método.

2.1. Método OnAppearing() se encarga de cargar los datos al iniciar la página.
  • Instrucción IList<User> result = await userDB.userFillEmail(strAuthentifyUser) que invoca al método para listar los datos del usuario.
2.2. El método cuentaEdit_Clicked(object sender, EventArgs e) se encarga de actualizar los datos.
  • Instrucción que se encarga de invocar al método para actualizar los datos  await userDB.UpdateItemAsync(users) y se encuentra en la clase UserDB.cs.
  • Recordemos que el Insert se realiza cuando el usuario se registra por primera ver y se genera la cuenta.
2.3. El método validateProperties() se encarga de validar los espacios y valores en nulo.

using AppDIAbetes.Data;
using AppDIAbetes.Models;
using AppDIAbetes.Utility;
using System;
using System.Collections.Generic;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace AppDIAbetes.Views.Options
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class TabPageAccount : ContentPage
    {
        //Managing user session
        private string strAuthentifyUser;
        public static string sstrEmailUser;
        LoginAccess OAuthLogin = new LoginAccess(sstrEmailUser);

        User users = new User();
        UserDB userDB = new UserDB();
  
        public TabPageAccount()
        {
            strAuthentifyUser = OAuthLogin.AuthentifyLogin();//Capture email
            InitializeComponent();
        }

        protected override async void OnAppearing()
        {
            base.OnAppearing();

            IList<User> result = await userDB.userFillEmail(strAuthentifyUser);

            foreach (var item in result)
            {
                labelId.Text = item.Id.ToString();
                entryEmail.Text = item.email;
                entryName.Text = item.name;
                entryPassword.Text = item.password;
                entryConfPassword.Text = item.password;
                valActive.IsToggled = item.active;
            }
        }

        private async void cuentaEdit_Clicked(object sender, EventArgs e)
        {
            if (validateProperties() == "Of")
            {
                await DisplayAlert("Alerta", "Debe ingresar los datos solicitados.", "Aceptar");

            }
            else if (!string.Equals(entryPassword.Text, entryConfPassword.Text))
            {
                warningPassword.Text = "Ingresar la misma contraseña";
                entryPassword.Text = string.Empty;
                entryConfPassword.Text = string.Empty;
                warningPassword.TextColor = Color.IndianRed;
                warningPassword.IsVisible = true;
            }
            else
            {
                users.Id = Convert.ToInt32(labelId.Text);
                users.email = entryEmail.Text.Trim();
                users.name = entryName.Text.Trim();
                users.password = entryPassword.Text.Trim();
                users.active = valActive.IsToggled;
                users.updDate = DateTime.Now;

                try
                {

                    var result = await DisplayAlert("Confirmar", "Estas seguro de actualizado los datos.", "Aceptar", "Cancelar");
                    if (result)
                    {
                        await userDB.UpdateItemAsync(users);
                        await DisplayAlert("Aviso", "Registro actualizado exitosamente.", "Aceptar");
                    }
                    else
                    {
                        return;
                    }
                   
                }
                catch (Exception ex)
                {
                    await DisplayAlert("Error", ex.ToString(), "OK");
                }
            }
        }

        string validateProperties()
        {
            string result = null;
            if ((string.IsNullOrWhiteSpace(entryPassword.Text)) ||
                (string.IsNullOrEmpty(entryPassword.Text)) ||
                (string.IsNullOrEmpty(entryPassword.Text)))
            {
                result = "Of";
            }
            else
            {
                result = "Ok";
            }
            return result;
        }
    }

}

Resultado:
Interfaz de la página TabPageAccount de tipo de Pagina de Contenido:

XAML - TabPageAccount.xaml

En la parte 2 revisaremos 👀la implementación de la interfaz TabPageInfo.xaml y el desarrollo de su CodeBehind.

De todas maneras gratitud a Dios 😊 y gracias a todos ustedes por la acogida de este nuevo articulo, éxitos y bendiciones 🙏 y un gran abrazo a todos ✌...!!!

Comentarios

Entradas más populares de este blog

Habilitar Usuario HR Oracle

Al realizar la primera instalación del Oracle, el usuario HR por defecto está bloqueado y por ende no podemos loguearnos como dicho usuario, lo que debe hacer son los siguiente pasos, aplicables para Linux o Windows.
1. Conectarse como usuario system o sysdba + contraseña haciendo uso del comando connect.
Usuario: system
Password: xxxx 


2. Hacer uso  del comando alter user hr account unlock desbloqueamos la cuenta.
alter user hr account unlock;

3. Escribimos el comando alter user HR identified by hr; con esto estamos diciendo que la contraseña será hr.

alter user HR identified by hr;

4. Ahora testeamos la conexión con el comando - conn hr/hr@xe. Si deseas después de conectarnos se puede realizar un select a la tabla employees del hr.


Resultado del select realizado
5. Con todos estos pasos realizados ya podemos logearnos desde cualquier IDE como el usuario hr  y la contraseña hr que definimos en el paso 3. 
Para finalizar nos loguearemos con el IDE Oracle SQL Developer.

Espero les sea de utilidad,…

Usuario SYS y SYSTEM - ORACLE

Usuario SYS y SYSTEM
Ambos usuario son creados de forma automática al crear la base de datos ORACLE y se otorga el rol de DBA.

SYS (password por defecto: CHANGE_ON_INSTALL).
SYSTEM (password por defecto: MANAGER).

Lo que se recomienda es cambiar el password de ambos usuarios por el tema de seguridad.

SYS:
Todas las tablas y vistas para el diccionario de datos de la base de datos están almacenados en el esquema SYS. Estas tablas y vistas son críticas para el funcionamiento de la base de datos ORACLE. Para mantener la integridad del diccionario de datos, las tablas del esquema SYS son manipulados solo por la base de datos. Nunca se debería modificar algo o crear tablas en el esquema del usuario SYS.

SYSTEM:
El usuario SYSTEM se utiliza para crear tablas y vistas adicionales que muestran información administrativa, tablas internas y vistas utilizado por varias opciones y herramientas de la base de datos ORACLE. No se recomienda utilizar el esquema SYSTEM para almacenar tablas de interés para usu…

Parámetro de entrada y salida – PL/SQL

Parámetro de entrada y salida – PL/SQL:
Los parámetros de entrada y salida no son los parámetros de inicialización de la base de datos ORACLE. Los parámetros de entra y salida son utilizados mayormente en implementaciones de funciones, procedimientos almacenados o bloques de código bajo el lenguaje del PL/SQL, se considera que ambos parámetros (entra y salida) puedan realizar operaciones en el mismo bloque PL/SQL, es decir, si enviamos un parámetro de entrada hará que cumpla cierta operación y retornara los valores de salida de dicha operación procesada de acuerdo al parámetro de ingresado. Es de acuerdo al caso que nos presenta en la implementación.
Algo importante al definir los parámetros, es saber y considerar cuántos tipos de parámetro existe si solo hablamos de entrada y salida, en realidad mi determinación seria 3 tipos:

Parámetros:

IN – entrada
OUT – salida
IN OUT – entrada salida

Parámetro IN – entrada:
El comportamiento común de estés tipos de parámetros es estar siempre pendiente d…