Está en la página 1de 22

Aplicaciones Móviles Multiplataforma Layouts

Aplicaciones Móviles Multiplataforma

“Local Database”

Pág. 1
Aplicaciones Móviles Multiplataforma Layouts

Laboratorio: LOCAL DATABASE

COMPETENCIAS

1. Comprender paradigmas de la programación orientada a objetos


2. Escribir funciones y procedimientos en lenguaje de programación C#
3. Declarar clases e instanciar objetos en Visual Studio con C#

EQUIPOS, MATERIALES, PROGRAMAS Y RECURSOS

● PC Personal.
● Sistema operativo Windows 7.
● Material disponible desde Tecsup Virtual.
● Software Visual Studio 2017

INTRODUCCIÓN

Existen diferentes lenguajes de programación orientado a objetos para escribir funciones y


procedimientos, pero el C# se acomoda a la necesidad del curso, porque nos va permitir
realizar aplicaciones multiplataforma en móviles con XAMARIN y VISUAL STUDIO 2017

PREPARACIÓN

El Alumno debe revisar previamente el material del curso.

REVISION DEL CASO PRÁCTICO

Pág. 2
Aplicaciones Móviles Multiplataforma Layouts

Crear nuevo Proyecto de nombre XamEFCore

Pág. 3
Aplicaciones Móviles Multiplataforma Layouts

Instalar desde el paquete Nuget


Microsoft.EntityFrameworkCore.Sqlite en el proyecto
compartido de Xamarin Forms.

Crear la siguiente estructura de carpetas en el proyecto


compartido de Xamarin Forms.

Pág. 4
Aplicaciones Móviles Multiplataforma Layouts

Agregar la clase AppDbContext.cs dentro de DataContext

using Microsoft.EntityFrameworkCore;
using XamEFCore.Models;

namespace XamEFCore.DataContext
{
public class AppDbContext : DbContext
{
string DbPath = string.Empty;

public AppDbContext(string dbPath)


{
this.DbPath = dbPath;
}

public DbSet<Artista> Artistas { get; set; }


public DbSet<Album> Albumes { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder


optionsBuilder)
{
optionsBuilder.UseSqlite($"Filename={DbPath}");
}
}
}

Agregar la clase Album.cs dentro de Models para la base de


datos

using System;
using System.Collections.Generic;
using System.Text;

namespace XamEFCore.Models
{
public class Album
{
public int AlbumID { get; set; }
public int ArtistaID { get; set; }
public Artista Artista { get; set; }

public string Titulo { get; set; }


public double Precio { get; set; }
public int Anio { get; set; }
}
}

Pág. 5
Aplicaciones Móviles Multiplataforma Layouts

Agregar la clase Artista.cs dentro de Models para la base de


datos

using System;
using System.Collections.Generic;
using System.Text;

namespace XamEFCore.Models
{
public class Artista
{
public int ArtistaID { get; set; }
public string Nombre { get; set; }
}
}

Modificar la clase App.xaml.cs agregando el método


GetContext e inicializando el context en el constructor

using Xamarin.Forms;
using XamEFCore.DataContext;
using XamEFCore.Interfaces;
using XamEFCore.Views;

namespace XamEFCore
{
public partial class App : Application
{
public App()
{
InitializeComponent();

GetContext().Database.EnsureCreated();
MainPage = new NavigationPage(new Views.MainPage());
}

// Método para obtener el contexto cuando se inicia la aplicación


public static AppDbContext GetContext()
{
string DbPath =
DependencyService.Get<IConfigDataBase>().GetFullPath("efCore.db");

return new AppDbContext(DbPath);


}

protected override void OnStart()


{
// Handle when your app starts
}

protected override void OnSleep()


{
// Handle when your app sleeps
}

Pág. 6
Aplicaciones Móviles Multiplataforma Layouts

protected override void OnResume()


{
// Handle when your app resumes
}
}
}

Agregar la clase DBDataAccess.cs dentro de carpeta Service


para la inyección de dependencia

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using XamEFCore.DataContext;

namespace XamEFCore.Services
{
public class DBDataAccess<T> where T : class
{
private readonly AppDbContext _context;

public DBDataAccess() => _context = App.GetContext();

public bool Create(T entity)


{
bool created;

try
{
_context.Entry(entity).State = EntityState.Added;
_context.SaveChanges();

created = true;
}
catch (Exception)
{
throw;
}

return created;
}

public IEnumerable<T> Get()


{
return _context.Set<T>().AsEnumerable();
}

public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)


{
return _context.Set<T>().Where(predicate).AsEnumerable<T>();
}

public IEnumerable<T> Get(Expression<Func<T, bool>> whereCondition =


null,

Pág. 7
Aplicaciones Móviles Multiplataforma Layouts

Func<IQueryable<T>, IOrderedQueryable<T>>
orderBy = null,
string includeProperties = "")
{
IQueryable<T> query = _context.Set<T>();

if (whereCondition != null)
{
query = query.Where(whereCondition);
}

foreach (var includeProperty in includeProperties.Split


(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}

if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}

public void Update(T entity)


{
_context.Entry(entity).State = EntityState.Modified;
_context.Set<T>().Attach(entity);
_context.SaveChanges();
}

public void Delete(T entity)


{
T existing = _context.Set<T>().Find(entity);

if (existing != null)
{
_context.Set<T>().Remove(existing);
_context.SaveChanges();
}
}

public async void SaveList(List<T> list)


{
try
{
foreach (var record in list)
{
_context.Add(record);
}
await _context.SaveChangesAsync();
}
catch (Exception)
{
throw;
}
}

public async void DeleteList(List<T> list)

Pág. 8
Aplicaciones Móviles Multiplataforma Layouts

{
try
{
foreach (var record in list)
{
_context.Remove(record);
}
await _context.SaveChangesAsync();
}
catch (Exception)
{
throw;
}
}
}
}

Agregar la clase IConfigDataBase.cs dentro de Interfaces


para hacer la dependencia de servicios en cada dispositivo

using System;
using System.Collections.Generic;
using System.Text;

namespace XamEFCore.Interfaces
{
public interface IConfigDataBase
{
string GetFullPath(string databaseFileName);
}
}

Pág. 9
Aplicaciones Móviles Multiplataforma Layouts

Ahora trabajaremos por Plataforma e implementaremos la


dependencia de servicio por Proyecto.

Creamos la carpeta Implementations en el Proyecto


Xamarin.Android

Agregamos la clase ConfigDataBase.cs dentro de la carpeta


Implementations

using System.IO;
using Xamarin.Forms;
using XamEFCore.Droid.Implementations;
using XamEFCore.Interfaces;

[assembly: Dependency(typeof(ConfigDataBase))]
namespace XamEFCore.Droid.Implementations
{
public class ConfigDataBase : IConfigDataBase
{
public string GetFullPath(string databaseFileName)
{
return
Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Pe
rsonal), databaseFileName);
}
}
}

Pág. 10
Aplicaciones Móviles Multiplataforma Layouts

Creamos la carpeta Implementations en el Proyecto


Xamarin.IOs

Agregamos la clase ConfigDataBase.cs dentro de la carpeta


Implementations

using System;
using System.IO;
using Xamarin.Forms;
using XamEFCore.Interfaces;
using XamEFCore.iOS.Implementations;

[assembly: Dependency(typeof(ConfigDataBase))]
namespace XamEFCore.iOS.Implementations
{
public class ConfigDataBase : IConfigDataBase
{
public string GetFullPath(string databaseFileName)
{
return
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"..", "Library", databaseFileName);
}
}
}

Pág. 11
Aplicaciones Móviles Multiplataforma Layouts

Ahora trabajadores con el MVVM


Agregar la clase BaseViewModelpara el Model View View
Model
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;

namespace XamEFCore.ViewModels
{
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged([CallerMemberName] string propertyName =


null)
{
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs(propertyName));
}

protected void SetValue<T>(ref T backingField, T value,


[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(backingField, value))
{
return;
}

backingField = value;
OnPropertyChanged(propertyName);
}
}
}

Pág. 12
Aplicaciones Móviles Multiplataforma Layouts

Agregar la clase MainViewModel.cs dentro de la carpeta


ViewModels
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using XamEFCore.Models;
using XamEFCore.Services;

namespace XamEFCore.ViewModels
{
public class MainViewModel : BaseViewModel
{
#region Attributes
private ObservableCollection<MenuItemViewModel> menu;
#endregion Attributes

#region Properties
public ObservableCollection<MenuItemViewModel> Menu
{
get { return this.menu; }
set { SetValue(ref this.menu, value); }
}
#endregion Properties

#region Constructor
public MainViewModel()
{
this.LoadMenu();

//this.SaveArtistasList();
}
#endregion Constructor

#region Methods
private void LoadMenu()
{
this.Menu = new ObservableCollection<MenuItemViewModel>();

this.Menu.Clear();
this.Menu.Add(new MenuItemViewModel { Id = 1, Option = "Crear" });
this.Menu.Add(new MenuItemViewModel { Id = 2, Option = "Lista de
Registros" });
}
#endregion Methods

DBDataAccess<Artista> dataService = new DBDataAccess<Artista>();


private void SaveArtistasList()
{
var artistas = new List<Artista>()
{
new Artista{ Nombre = "Arjona" },
new Artista{ Nombre = "Luismi" },
new Artista{ Nombre = "Kalimba" }
};

dataService.SaveList(artistas);
}
}

Pág. 13
Aplicaciones Móviles Multiplataforma Layouts

Agregar la clase MenuItemViewModel.cs dentro de la


carpeta ViewModels

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;
using XamEFCore.Views;

namespace XamEFCore.ViewModels
{
public class MenuItemViewModel
{
#region Attributes
public int Id { get; set; }
public string Option { get; set; }
public string Icon { get; set; }
#endregion Attributes

#region Commands
public ICommand SelectMenuItemCommand
{
get
{
return new Command(SelectMenuItemExecute);
}
}
#endregion Commands

#region Methods
private void SelectMenuItemExecute()
{
if(this.Id == 1)
Application.Current.MainPage.Navigation.PushAsync(new
AlbumPage());

else
Application.Current.MainPage.Navigation.PushAsync(new
AlbumesPage());
}
#endregion Methods
}
}

Pág. 14
Aplicaciones Móviles Multiplataforma Layouts

Agregar la clase AlbumesViewModel.cs dentro de la


carpeta ViewModels

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using Xamarin.Forms;
using XamEFCore.Models;
using XamEFCore.Services;

namespace XamEFCore.ViewModels
{
public class AlbumesViewModel : BaseViewModel
{
#region Services
private readonly DBDataAccess<Artista> dataServiceArtistas;
private readonly DBDataAccess<Album> dataServiceAlbumes;
#endregion Services

#region Attributes
private ObservableCollection<Artista> artistas;
private ObservableCollection<Album> albumes;
private Artista selectedArtista;
private string titulo;
private double precio;
private int anio;
#endregion Attributes

#region Properties
public ObservableCollection<Artista> Artistas
{
get { return this.artistas; }
set { SetValue(ref this.artistas, value); }
}

public ObservableCollection<Album> Albumes


{
get { return this.albumes; }
set { SetValue(ref this.albumes, value); }
}

public Artista SelectedArtista


{
get { return this.selectedArtista; }
set { SetValue(ref this.selectedArtista, value); }
}

public string Titulo


{
get { return this.titulo; }
set { SetValue(ref this.titulo, value); }
}

public double Precio


{
get { return this.precio; }
set { SetValue(ref this.precio, value); }

Pág. 15
Aplicaciones Móviles Multiplataforma Layouts

public int Anio


{
get { return this.anio; }
set { SetValue(ref this.anio, value); }
}
#endregion Properties

#region Constructor
public AlbumesViewModel()
{
this.dataServiceArtistas = new DBDataAccess<Artista>();
this.dataServiceAlbumes = new DBDataAccess<Album>();

//this.CreateArtistas();

this.LoadArtistas();
this.LoadAlbumes();

this.Anio = DateTime.Now.Year;
}
#endregion Constructor

#region Commands
public ICommand CreateCommand
{
get
{
return new Command(async()=>
{
var newAlbum = new Album()
{
ArtistaID = this.SelectedArtista.ArtistaID,
Titulo = this.Titulo,
Precio = this.Precio,
Anio = this.Anio
};

if(newAlbum != null)
{
if (this.dataServiceAlbumes.Create(newAlbum))
{
await
Application.Current.MainPage.DisplayAlert("Operación Exitosa",

$"Albúm del artista: {this.SelectedArtista.Nombre} " +

$"creado correctamente en la base de datos",

"Ok");

this.SelectedArtista = null;
this.Titulo = string.Empty;
this.Precio = 0;
this.Anio = DateTime.Now.Year;
}

else
await
Application.Current.MainPage.DisplayAlert("Operación Fallida",

Pág. 16
Aplicaciones Móviles Multiplataforma Layouts

$"Error al crear el Albúm en la base de datos",

"Ok");
}
});
}
}
#endregion Commands

#region Methods
private void LoadArtistas()
{
var artistasDB = this.dataServiceArtistas.Get().ToList() as
List<Artista>;
this.Artistas = new ObservableCollection<Artista>(artistasDB);
}

private void LoadAlbumes()


{
var albumesDB = this.dataServiceAlbumes.Get(null, null,
"Artista").ToList() as List<Album>;
this.Albumes = new ObservableCollection<Album>(albumesDB);
}

private void CreateArtistas()


{
var artistas = new List<Artista>()
{
new Artista { Nombre = "Ricardo Arjona" },
new Artista { Nombre = "Kalimba" },
new Artista { Nombre = "Luis Miguel" }
};

this.dataServiceArtistas.SaveList(artistas);
}
#endregion Methods
}
}

Pág. 17
Aplicaciones Móviles Multiplataforma Layouts

Ahora trabajaremos con las vistas de la página


Agregar el AlbumesPage.xaml content page dentro de la
carpeta views

<?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"
xmlns:ViewModel="clr-namespace:XamEFCore.ViewModels"
x:Class="XamEFCore.Views.AlbumesPage"
Title="Lista de Albumes">

<ContentPage.BindingContext>
<ViewModel:AlbumesViewModel/>
</ContentPage.BindingContext>

<ContentPage.Content>
<StackLayout>
<StackLayout.Padding>
<OnPlatform
x:TypeArguments="Thickness"
Android="20"
iOS="50"/>
</StackLayout.Padding>

<ListView
ItemsSource="{Binding Albumes}"
HasUnevenRows="True"
SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame
CornerRadius="20"
HasShadow="True"
Margin="3">

<StackLayout
Orientation="Vertical">
<Grid
VerticalOptions="CenterAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>

<Label
Grid.Row="0"
Grid.Column="0"
Text="Artista: "
FontAttributes="Bold"/>

<Label
Grid.Row="0"
Grid.Column="1"

Pág. 18
Aplicaciones Móviles Multiplataforma Layouts

Text="{Binding Artista.Nombre}"/>

<Label
Grid.Row="1"
Grid.Column="0"
Text="Título: "
FontAttributes="Bold"/>

<Label
Grid.Row="1"
Grid.Column="1"
Text="{Binding Titulo}"/>

<Label
Grid.Row="2"
Grid.Column="0"
Text="Precio: "
FontAttributes="Bold"/>

<Label
Grid.Row="2"
Grid.Column="1"
Text="{Binding Precio}"/>

<Label
Grid.Row="3"
Grid.Column="0"
Text="Año: "
FontAttributes="Bold"/>

<Label
Grid.Row="3"
Grid.Column="1"
Text="{Binding Anio}"/>
</Grid>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Pág. 19
Aplicaciones Móviles Multiplataforma Layouts

Agregar el AlbumPage.xaml content page dentro de la


carpeta views
<?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"
xmlns:ViewModel="clr-namespace:XamEFCore.ViewModels"
x:Class="XamEFCore.Views.AlbumPage"
Title="Crear nuevo Album">

<ContentPage.BindingContext>
<ViewModel:AlbumesViewModel/>
</ContentPage.BindingContext>

<ContentPage.Content>
<StackLayout>
<StackLayout.Padding>
<OnPlatform
x:TypeArguments="Thickness"
Android="20"
iOS="50"/>
</StackLayout.Padding>

<Label
Text="Artista"/>
<Picker
Title="Selecciona un Artista"
ItemsSource="{Binding Artistas}"
ItemDisplayBinding="{Binding Nombre}"
SelectedItem="{Binding SelectedArtista}"/>

<Label
Text="Título"/>
<Entry
Placeholder="Título"
Text="{Binding Titulo}"/>

<Label
Text="Precio"/>
<Entry
Placeholder="Precio"
Text="{Binding Precio}"/>

<Label
Text="Año"/>
<Entry
Placeholder="Año"
Text="{Binding Anio}"/>

<Button
Text="Guardar"
Command="{Binding CreateCommand}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Pág. 20
Aplicaciones Móviles Multiplataforma Layouts

Agregar el MainPage.xaml content page dentro de la


carpeta views

<?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"
xmlns:ViewModel="clr-namespace:XamEFCore.ViewModels"
x:Class="XamEFCore.Views.MainPage"
Title="Xamarin Forms">

<ContentPage.BindingContext>
<ViewModel:MainViewModel/>
</ContentPage.BindingContext>

<StackLayout
Margin="10,10,10,10">
<StackLayout
Orientation="Horizontal">
<Frame
CornerRadius="20"
WidthRequest="50"
HeightRequest="50"
HorizontalOptions="Start">
<Image
Source="monkey.png"
WidthRequest="200"
HeightRequest="200"/>
</Frame>
<Label
Text="Xamarin + EF Core"
VerticalOptions="CenterAndExpand"
FontSize="Large"
FontAttributes="Italic"
Margin="20"
HorizontalOptions="CenterAndExpand"/>
</StackLayout>

<StackLayout
BackgroundColor="#0080FF"
Padding="5,5,5,5"
Margin="0,5,0,5">
<Label
Text="SELECCIONE LA OPCIÓN A REALIZAR"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
HorizontalOptions="Center"/>
</StackLayout>

<ListView
ItemsSource="{Binding Menu}"
HasUnevenRows="True"
SeparatorVisibility="None">
<ListView.ItemTemplate>

Pág. 21
Aplicaciones Móviles Multiplataforma Layouts

<DataTemplate>
<ViewCell>
<Frame
CornerRadius="20"
HasShadow="True"
Margin="3">

<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding
SelectMenuItemCommand}"/>
</Frame.GestureRecognizers>

<StackLayout
Orientation="Horizontal">
<Label
Text="{Binding Id}"
IsVisible="False"/>
<Label
Text="{Binding Option}"
VerticalOptions="Center"
FontSize="Large"/>
<Image
Source="ic_chevron_right"
HorizontalOptions="EndAndExpand"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

</StackLayout>

</ContentPage>

Pág. 22

También podría gustarte