Ir al contenido principal

Xamarin.Forms - Tabbed Page con SQLite - Parte 2

Hola nuevamente; espero estén todos bien, hoy les comparto la parte de 2 del control Tabbed Page. Implementaremos el Tabbed Page 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).

Requisitos:
Microsoft Visual Studio Community 2019.
Xamarin.Froms - XAML.
SQLite - Gestión de datos local.
Revisar - Tabbed Page con SQLite - Parte 1


Diseño de Interfaz:
Ahora en la pagina TabPageInfo.xaml agregamos los siguientes elementos, además importar la referencia TabPageInfo (agregar la siguiente línea xmlns:local="clr-namespace:AppDIAbetes.Views.Options.TabPageInfo"):

<?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.TabPageInfo"
             Title="Info"
             IconImageSource="UserInfo32.png"
             BackgroundColor="#FFFFFF">
    <ContentPage.Content>
        <AbsoluteLayout BackgroundColor="White" Margin="5,0,5,5">
            <FlexLayout IsVisible="True" JustifyContent="SpaceEvenly" Direction="Column" AlignItems="Center" Margin="10,0,10,0" >
                    <Grid BackgroundColor="Transparent">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                    <StackLayout Grid.Row="0" Grid.Column="0" Grid.RowSpan="3">
                        <Frame>
                            <Image x:Name="photoUser" HorizontalOptions="Center" HeightRequest="158" WidthRequest="120" BackgroundColor="Transparent"/>
                        </Frame>
                    </StackLayout>                       
                    <!--</Frame>-->
                        <StackLayout Grid.Row="0" Grid.Column="1">
                            <Entry x:Name="entryFirstName" Placeholder="Nombres" Keyboard="Text" FontSize="Small" TextColor="Black"/>
                        </StackLayout>

                        <StackLayout Grid.Row="1" Grid.Column="1">
                            <Entry x:Name="entryLastName" Placeholder="Apellidos" Keyboard="Text" FontSize="Small" TextColor="Black"/>
                        </StackLayout>

                        <StackLayout Grid.Row="2" Grid.Column="1" HorizontalOptions="Start" Orientation="Horizontal">
                            <Label Text="Fecha Nac." TextColor="Black" HorizontalOptions="Start" VerticalOptions="Center" FontSize="Small"/>

                        <DatePicker Format="dd/MM/yyyy" Grid.Row="2" Grid.Column="1"
                                         x:Name="dpFechaNac" TextColor="Black" FontSize="Small"           
                                         HorizontalOptions="EndAndExpand"  BackgroundColor="Transparent"
                                         MinimumDate="01/01/1920" MaximumDate="12/31/2030" />
                        </StackLayout>

                        <StackLayout Grid.Row="3" Grid.Column="1" HorizontalOptions="Start" Orientation="Horizontal">
                            <Label Text="(+51)" TextColor="Black" HorizontalOptions="Start" VerticalOptions="Center" FontSize="Small"/>
                            <Entry x:Name="entryPhone" Placeholder="Celular" MaxLength="9" Keyboard="Telephone" FontSize="Small" TextColor="Black" WidthRequest="120"/>
                        </StackLayout>                   

                        <StackLayout Grid.Row="3" Grid.Column="0" HorizontalOptions="Center" Orientation="Horizontal">
                            <ImageButton x:Name="selPhoto" Clicked="selPhoto_Clicked" Source="folderPictures48.png"/>
                            <ImageButton x:Name="takePhoto" Clicked="takePhoto_Clicked" Source="folderPhoto48.png"/>
                        </StackLayout>

                        <StackLayout Grid.Row="4" Grid.ColumnSpan="2" HorizontalOptions="CenterAndExpand" Orientation="Horizontal">
                            <Label Grid.Column="0" Text="Tipo de Persona" TextColor="Black" WidthRequest="110" HorizontalOptions="Start" VerticalOptions="Center" FontSize="Small"/>
                            <Picker Grid.Column="1"
                                    x:Name="pTipyPeople"
                                    Title="Seleccionar" FontSize="Small"
                                    TextColor="Black" WidthRequest="208"
                                    SelectedIndexChanged="OnPickerSelectedIndexChanged">
                                <Picker.Items>
                                    <x:String>PACIENTE</x:String>
                                    <x:String>MÉDICO TRATANTE</x:String>
                                </Picker.Items>
                            </Picker>
                        </StackLayout>
                    </Grid>
              
                    <Label x:Name="warningPhone" Text="" IsVisible="False" TextColor="#FF5959" FontSize="12" BackgroundColor="Transparent" FlexLayout.AlignSelf="End"/>

                    <StackLayout HorizontalOptions="Start" Orientation="Horizontal">
                        <Label x:Name="labelPhoneMedico" Text="N° Teléfono" TextColor="Black" WidthRequest="100" HorizontalOptions="Start" VerticalOptions="Center" FontSize="Small" IsVisible="False"/>
                        <Entry x:Name="entryPhoneMedico" Placeholder="Teléf de tu médico tratante" Keyboard="Telephone" FontSize="Small" TextColor="Black" WidthRequest="210" IsVisible="False"/>
                    </StackLayout>

                    <StackLayout HorizontalOptions="Start" Orientation="Horizontal">
                        <Label x:Name="labelEmailMedico" Text="Email" TextColor="Black" WidthRequest="100" HorizontalOptions="Start" VerticalOptions="Center" FontSize="Small" IsVisible="False"/>
                        <Entry x:Name="entryEmailMedico" Placeholder="Email de tu médico tratante" Keyboard="Email" FontSize="Small" TextColor="Black" WidthRequest="210" IsVisible="False" />
                    </StackLayout>

                    <Button x:Name="infoInsert" Clicked="infoInsert_Clicked" FontSize="Medium" TextColor="White" BorderColor="Black" BackgroundColor="#6fb7ff"  CornerRadius="5" FlexLayout.AlignSelf="Stretch" Text="Actualizar"></Button>
               
            </FlexLayout>
        </AbsoluteLayout>
    </ContentPage.Content>   

</ContentPage>

Crear Clases:
Seguidamente creamos la clase People.cs en el sub directorio Views\Models y agregamos los siguientes atributos:

using SQLite;
using System;

namespace AppDIAbetes.Models
{                
    public class People
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
        public DateTime birthdate { get; set; }
        public string phoneUser { get; set; }
        public string phoneMedico { get; set; }
        public string emailMedico { get; set; }
        public int IdUser { get; set; }
        public int IdRole { get; set; }
        public DateTime regDate { get; set; }
        public DateTime updDate { get; set; }
        public bool chkViewPass { get; set; }
        public bool chkChangePass { get; set; }
        public bool chkSendReport { get; set; }
    }
}

Para finalizar creamos la clase PeopleDB.cs en el sub directorio Views\Data y agregamos las siguientes funciones para dar la funcionalidad con conexión a base de datos del SQLite (la región conexionbd son instrucciones de conexión a la base de datos):

using AppDIAbetes.Models;
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AppDIAbetes.Data
{
    public class PeopleDB
    {
        #region conexionbd
        static readonly Lazy<SQLiteAsyncConnection> lazyInitializer = new Lazy<SQLiteAsyncConnection>(() =>
        {
            return new SQLiteAsyncConnection(DataBase.DatabasePath, DataBase.Flags);
        });

        static SQLiteAsyncConnection Database => lazyInitializer.Value;
        static bool initialized = false;

        public PeopleDB()
        {
            InitializeAsync().SafeFireAndForget(false);
        }

        async Task InitializeAsync()
        {
            if (!initialized)
            {
                if (!Database.TableMappings.Any(m => m.MappedType.Name == typeof(People).Name))
                {
                    await Database.CreateTablesAsync(CreateFlags.None, typeof(People)).ConfigureAwait(false);
                    initialized = true;
                }
            }
        }
        #endregion

        #region metodos crud 
        public Task<List<People>> peopleFillIdUse(int intIdUser)
        {
            return Database.QueryAsync<People>("Select * from People Where IdUser=?", intIdUser);
        }

        public string savePeopleInfo(People people)
        {
            string srtResult = null;

            IEnumerable<People> result = valPeople(people.IdUser);
            if(result.Count()== 0) {
                Database.InsertAsync(people);
                srtResult = "Ins";
            }
            else{
                Database.QueryAsync<People>("Update People Set firstName=?, lastName=?, birthdate=?, phoneUser=?, phoneMedico=?, emailMedico=?, IdRole=?, updDate=? Where Id=? and IdUser=?", people.firstName, people.lastName, people.birthdate, people.phoneUser, people.phoneMedico, people.emailMedico, people.IdRole, people.updDate, people.Id, people.IdUser);
                srtResult = "Upd";
            }
            return srtResult;
        }

        public string savePeopleConfig(People people)
        {
            string srtResult = null;
        
            Database.QueryAsync<People>("Update People Set chkViewPass=?, chkChangePass=?, chkSendReport=?, updDate=? Where Id=? and IdUser=?", people.chkViewPass, people.chkChangePass, people.chkSendReport, people.updDate, people.Id, people.IdUser);
            srtResult = "Upd";
            return srtResult;
        }

        public IEnumerable<People> valPeople(int intIdUser)
        {
            var result = Database.QueryAsync<People>("Select * from People p, User u Where p.IdUser=u.Id and p.IdUser=?", intIdUser);
            return result.Result;
        }
        #endregion
    }

}

Implementar el CodeBehind:
El en CodeBehind de la pagina de contenido TabPageInfo.xaml.cs creamos las siguientes instrucciones (la sección sombreado de color //Managing user session corresponde a capturar de la sesión de logeo):

using AppDIAbetes.Utility;
using Plugin.Media;
using Plugin.Media.Abstractions;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using AppDIAbetes.Models;
using AppDIAbetes.Data;

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

        private int intId, intIdUser;
        private string strUser;

        People people = new People();
        PeopleDB peopleDB = new PeopleDB();
        UserDB userDB = new UserDB();

        public TabPageInfo()
        {
            strAuthentifyUser = OAuthLogin.AuthentifyLogin();
            InitializeComponent();
            this.BindingContext = new Models.CamarePhoto();
            vCaptureIdUser();
        }

        private async void vCaptureIdUser() {
            IList<User> result = await userDB.userFillEmail(strAuthentifyUser);

            if (result.Count == 1)
            {
                foreach (var item in result)
                {
                    intIdUser = item.Id;//Id de la tabla User
                    strUser = item.name;
                }
            }
            else {
                await DisplayAlert("Alerta", "Ocurrio un problema al cargar los registros.", "Aceptar");
            }
        }

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

            IList<People> result = await peopleDB.peopleFillIdUse(intIdUser);

            foreach (var item in result)
            {
                intId = item.Id;
                entryFirstName.Text = item.firstName;
                entryLastName.Text = item.lastName;
                dpFechaNac.Date = item.birthdate;
                entryPhone.Text = item.phoneUser;
                pTipyPeople.SelectedIndex = item.IdRole;

                entryPhoneMedico.Text = item.phoneMedico;
                entryEmailMedico.Text = item.emailMedico;
            }
        }

        #region control type people
        void OnPickerSelectedIndexChanged(object sender, EventArgs e)
        {
            var picker = (Picker)sender;
            int selectedIndex = picker.SelectedIndex;

            if (selectedIndex != -1)
            {
                if (selectedIndex == 0)// 0 PACIENTE
                {
                    labelPhoneMedico.IsVisible = true;
                    entryPhoneMedico.IsVisible = true;
                    labelEmailMedico.IsVisible = true;
                    entryEmailMedico.IsVisible = true;
                }
                else if(selectedIndex == 1) {//1 MEDICO TRATANTE
                    labelPhoneMedico.IsVisible = false;
                    entryPhoneMedico.IsVisible = false;
                    labelEmailMedico.IsVisible = false;
                    entryEmailMedico.IsVisible = false;
                }
            }
        }
        #endregion

        #region CRUD
        private async void infoInsert_Clicked(object sender, EventArgs e)
        {
            people.Id = intId;//Id de la tabla People
            people.firstName = entryFirstName.Text;
            people.lastName = entryLastName.Text;
            people.birthdate = dpFechaNac.Date;
            people.phoneUser = entryPhone.Text;
            people.phoneMedico = entryPhoneMedico.Text;
            people.emailMedico = entryEmailMedico.Text;

            people.IdUser = intIdUser;//Id de la tabla User
            people.IdRole = pTipyPeople.SelectedIndex;        

            if (people.Id == 0)
            {
                people.regDate = DateTime.Now;
                people.updDate = DateTime.Now;

                people.chkViewPass = false;
                people.chkChangePass = false;
                people.chkSendReport = false;

                var returnResult = peopleDB.savePeopleInfo(people);
                if (returnResult == "Ins")
                    await DisplayAlert("Aviso", "Registros ingresado con éxito.", "Aceptar");
            }
            else {
                people.updDate = DateTime.Now;

                var returnResult = peopleDB.savePeopleInfo(people);
                if (returnResult == "Upd")
                    await DisplayAlert("Aviso", "Registros actualizado con éxito.", "Aceptar");
            }
        }
        #endregion       
    }
}

Resultado:
Interfaz de la página TabPageInfo de tipo de Pagina de Contenido (la sección de tomar foto o cargar imagen lo veremos en otro artículo):
XAML TabPageInfo.xaml 
En la parte 3 revisaremos 👀la implementación de la interfaz TabPageConfig.xaml y el desarrollo de su CodeBehind del TabPageConfig.xaml.cs.

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…