Syncfusion para dummies en Xamarin.Forms
Para esta entrada como parte del #AdvientoXamarin he pensado en dar una pequeña reseña del cómo podemos implementar los controles de Syncfusion, para los que estamos en el área estos controles dan un gran impacto visual a nuestras apps, tienes que saber que Syncfusion ofrece una licencia completamente gratuita para empresas o developers para usar sus productos siempre y cuando cumplas lo siguientes requisitos:
En esta pantalla es necesario seleccionar por ahora Xamarin
Guarda muy bien tu clave, y aprovechando copiala a tu portapapeles
Además es necesario que actualices tus nugets, y como extra que tu proyecto android apunte a la última versión de la api de android en mi caso Android 9 - Pie
5- Comencemos con la interfaz gráfica
Que les parece si creamos una vista que implemente un perfil de usuario, para ello manejaremos algunos controles de syncfusion los cuales son:
En este código estamos usando MVVM con un objeto principal para la transferencia de información mejor conocido como Dto con el cual pretendemos enviar toda la información capturada en el perfil del usuario (este Dto implementa la interfaz INotifyPropertyChanged), la imagen es representativa y esta adjunta directamente en la carpeta Drawable, usamos propiedades para manejar los errores de captura al momento de guardar.
Muy importante, recuerda hacer la parte del binding en el código detrás de la vista.
Ahora pasemos al código ViewModel, en donde de entrada también aplicamos la interfaz INotifyPropertyChanged, para mediante algunas propiedades manejar el comportamiento de ciertos controles, no olvides manejar regiones para un código más limpio.
El Dto de usuario que tendría las siguientes propiedades
Ya para concluir, el resultado que podrás ver es algo parecido a esto
Todo este código lo podrás encontrar en mi repo de Git, así cerramos esta entrada espero que te sea útil la información. Cualquier duda puedes dejarla en el apartado de comentario, estaré pendiente si puedo ayudar en algo :)
- Si obtienes menos de 1 millón de dólares al año y un equipo de 5 o menos developers
Así que comencemos aquí habrá que realizar el registro hasta tener acceso a la consola (tendrás que dar tu número telefónico ya que te hacen una llamada).
1- Obtener la llave de nuestra licencia
Este paso es muy importante para evitar el mensaje de aviso, al inicio de nuestra app, les dejo una serie de imágenes para que vean el proceso de obtener la clave de licencia.
En esta pantalla es necesario seleccionar por ahora Xamarin
Guarda muy bien tu clave, y aprovechando copiala a tu portapapeles
2- Creación del proyecto y configuración con la clave
Pasemos a crear un proyecto Cross platform en visual studio (por ahora omitimos este proceso ya que es relativamente simple)
Syncfusion cuenta con una gran gama de controles las cuales puedes encontrar aquí cada control cuenta con su respectiva documentación desde la instalación hasta su integración.
Aquí nosotros veremos la integración de un par de ellos y claro usando buenas prácticas como:
- MVVM (sin framework)
- Clean code
- Entre otras buenas practicas (documentación de código, uso de regiones)
3- Integración de un combo con autocompletado
Accede a los nugets de la solución y busca Syncfusion.Xamarin.SfAutoComplete tendrás que instalarlo en todos tus proyectos (android, ios) en nuestro caso el proyecto solo abarca android como plataforma de alcance, con esta instalación también se instalan las referencias necesarias.
Antes de continuar... quiero comentarte que nosotros estaremos creando los controles por medio de XAML (no del backend) en mi experiencia procuro no utilizar el código detrás de XAML, eso a criterio de cada uno de nosotros como programadores.
Ahora si continuemos :)
4- Preparación del proyecto con la llave de nuestra cuenta de syncfusion
Habrá que establecer el licenciamiento de nuestro proyecto para poder utilizar los controles de Syncfusion, para ello en el constructor de tu clase App.xaml.cs deberás establecer el siguiente código:
Ahora si continuemos :)
4- Preparación del proyecto con la llave de nuestra cuenta de syncfusion
Habrá que establecer el licenciamiento de nuestro proyecto para poder utilizar los controles de Syncfusion, para ello en el constructor de tu clase App.xaml.cs deberás establecer el siguiente código:
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("KEY DE SYNCFUSION");
Además es necesario que actualices tus nugets, y como extra que tu proyecto android apunte a la última versión de la api de android en mi caso Android 9 - Pie
5- Comencemos con la interfaz gráfica
Que les parece si creamos una vista que implemente un perfil de usuario, para ello manejaremos algunos controles de syncfusion los cuales son:
Todos los controles los puedes encontrar aquí en caso de que quieras implementar alguno más, sé que son pocos pero la idea es darte la intro a syncfusion y que sepas configurarlo para usar los controles.
Nuestra interfaz nos quedaría así, en la vista MainPage que viene por default en el proyecto:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="XamarinAdvientoSyncfusion.MainPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:autocomplete="clr-namespace:Syncfusion.SfAutoComplete.XForms;assembly=Syncfusion.SfAutoComplete.XForms" xmlns:avatarView="clr-namespace:Syncfusion.XForms.AvatarView;assembly=Syncfusion.Core.XForms" xmlns:buttons="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms" xmlns:popupLayout="clr-namespace:Syncfusion.XForms.PopupLayout;assembly=Syncfusion.SfPopupLayout.XForms" xmlns:textInputLayout="clr-namespace:Syncfusion.XForms.TextInputLayout;assembly=Syncfusion.Core.XForms" Title="Mi perfil"> <ContentPage.ToolbarItems> <ToolbarItem Command="{Binding GuardarPerfilCommand}" Text="Guardar" /> </ContentPage.ToolbarItems> <ScrollView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <StackLayout Padding="20" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <avatarView:SfAvatarView Margin="0,15,0,0" ContentType="Custom" CornerRadius="150" HeightRequest="250" HorizontalOptions="Center" ImageSource="stock.jpg" VerticalOptions="Center" WidthRequest="250" /> <textInputLayout:SfTextInputLayout ContainerType="None" ErrorText="{Binding Usuario.MensajeErrorUsuario}" HasError="{Binding Usuario.ErrorUsuario}" HelperText="Captura tu(s) nombre(s)" Hint="Nombre(s)" ReserveSpaceForAssistiveLabels="True"> <Entry Text="{Binding Usuario.Nombre, Mode=TwoWay}" /> </textInputLayout:SfTextInputLayout> <textInputLayout:SfTextInputLayout ContainerType="None" ErrorText="{Binding Usuario.MensajeErrorApellidos}" HasError="{Binding Usuario.ErrorApellidos}" HelperText="Captura tus apellidos" Hint="Apellido(s)" ReserveSpaceForAssistiveLabels="True"> <Entry Text="{Binding Usuario.Apellidos, Mode=TwoWay}" /> </textInputLayout:SfTextInputLayout> <textInputLayout:SfTextInputLayout ContainerType="None" ErrorText="{Binding Usuario.MensajeErrorNick}" HasError="{Binding Usuario.ErrorNick}" HelperText="¿Cual será tu nombre clave?" Hint="Nick" ReserveSpaceForAssistiveLabels="True"> <Entry Text="{Binding Usuario.Nick, Mode=TwoWay}" /> </textInputLayout:SfTextInputLayout> <textInputLayout:SfTextInputLayout CharMaxLength="8" ContainerType="None" EnablePasswordVisibilityToggle="True" ErrorText="{Binding Usuario.MensajeErrorPass}" HasError="{Binding Usuario.ErrorPass}" HelperText="Captura tu contraseña" Hint="Contraseña" ReserveSpaceForAssistiveLabels="True" ShowCharCount="true"> <Entry Text="{Binding Usuario.Pass, Mode=TwoWay}" /> </textInputLayout:SfTextInputLayout> <autocomplete:SfAutoComplete AutoCompleteMode="Suggest" ClearButtonColor="Black" DataSource="{Binding ListaEstados}" DisplayMemberPath="Nombre" DropDownItemHeight="35" HeightRequest="45" HighlightedTextColor="Red" IsFocused="True" MaximumDropDownHeight="150" MinimumPrefixCharacters="1" NoResultsFoundText="Sin coincidencias" PopupDelay="0" SelectedItem="{Binding Usuario.Estado}" ShowClearButton="True" SuggestionMode="Contains" Text="{Binding Usuario.Estado, Mode=TwoWay}" TextColor="Black" TextHighlightMode="FirstOccurrence" TextSize="16" Watermark="Buscar estado..." WatermarkColor="#adb2bb" /> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="70*" /> <ColumnDefinition Width="30*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <textInputLayout:SfTextInputLayout Grid.Column="0" ContainerType="None" ErrorText="{Binding MensajeErrorHobbie}" HasError="{Binding ErrorHobbie}" HelperText="Captura un hobbie" Hint="Este es uno de mis hobbies" ReserveSpaceForAssistiveLabels="True"> <Entry Text="{Binding NuevoHobbie, Mode=TwoWay}" /> </textInputLayout:SfTextInputLayout> <buttons:SfButton Grid.Column="1" Command="{Binding AgregarHobbieCommand}" Text="Agregar" /> </Grid> <buttons:SfChipGroup DisplayMemberPath="Nombre" ItemsSource="{Binding Usuario.Hobbies}"> <buttons:SfChipGroup.ChipLayout> <FlexLayout AlignContent="Start" AlignItems="Start" Direction="Row" HorizontalOptions="Start" JustifyContent="Start" VerticalOptions="Center" Wrap="Wrap" /> </buttons:SfChipGroup.ChipLayout> </buttons:SfChipGroup> <popupLayout:SfPopupLayout IsOpen="{Binding IsSuccess}"> <popupLayout:SfPopupLayout.PopupView> <popupLayout:PopupView AnimationMode="Zoom" ShowFooter="False" AutoSizeMode="Height" ShowHeader="False"> <popupLayout:PopupView.ContentTemplate> <DataTemplate> <Label Padding="15" BackgroundColor="White" HorizontalOptions="FillAndExpand" Text="Los datos fueron registrados con éxito" /> </DataTemplate> </popupLayout:PopupView.ContentTemplate> </popupLayout:PopupView> </popupLayout:SfPopupLayout.PopupView> </popupLayout:SfPopupLayout> </StackLayout> </ScrollView> </ContentPage>
Muy importante, recuerda hacer la parte del binding en el código detrás de la vista.
using Xamarin.Forms;
using XamarinAdvientoSyncfusion.ViewModels;
namespace XamarinAdvientoSyncfusion
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new PerfilUsuarioViewModel();
}
}
}
Ahora pasemos al código ViewModel, en donde de entrada también aplicamos la interfaz INotifyPropertyChanged, para mediante algunas propiedades manejar el comportamiento de ciertos controles, no olvides manejar regiones para un código más limpio.
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
using XamarinAdvientoSyncfusion.Dtos;
namespace XamarinAdvientoSyncfusion.ViewModels
{
public class PerfilUsuarioViewModel:INotifyPropertyChanged
{
#region VariablesObjetos
private DtoHobbie hobbie;
private DtoUsuario usuario=new DtoUsuario();
public DtoUsuario Usuario
{
get { return usuario; }
set { OnSetProperty("Usuario"); }
}
private string nuevoHobbie;
public string NuevoHobbie
{
get { return nuevoHobbie; }
set
{
nuevoHobbie = value;
OnSetProperty("NuevoHobbie");
}
}
private bool isSuccess;
public bool IsSuccess
{
get { return isSuccess; }
set
{
isSuccess = value; OnSetProperty("IsSuccess"); }
}
private string mensajeErrorHobbie;
public string MensajeErrorHobbie
{
get { return mensajeErrorHobbie; }
set { OnSetProperty("MensajeErrorHobbie"); }
}
private bool errorHobbie;
public bool ErrorHobbie
{
get { return errorHobbie; }
set { OnSetProperty("ErrorHobbie"); }
}
public ICommand AgregarHobbieCommand { get; set; }
public ICommand GuardarPerfilCommand { get; set; }
public ObservableCollection ListaEstados { get; set; }
#endregion
#region Metodos
public PerfilUsuarioViewModel()
{
LlenarEstadosCiudades();
AgregarHobbieCommand=new Command(AgregarHobbie);
GuardarPerfilCommand = new Command(GuardarPerfil);
}
private void GuardarPerfil()
{
if (ValidarDatos())
{
IsSuccess = true;
}
}
private bool ValidarDatos()
{
bool datosValidos=true;
if (string.IsNullOrWhiteSpace(Usuario.Nombre))
{
Usuario.ErrorUsuario = true;
Usuario.MensajeErrorUsuario = "Nombre, es obligatorio";
datosValidos = false;
}
else
{
Usuario.ErrorUsuario = false;
Usuario.MensajeErrorUsuario = "";
}
if (string.IsNullOrWhiteSpace(Usuario.Apellidos))
{
Usuario.ErrorApellidos = true;
Usuario.MensajeErrorApellidos = "Apellidos, es obligatorio";
datosValidos = false;
}
else
{
Usuario.ErrorApellidos = false;
Usuario.MensajeErrorApellidos = "";
}
if (string.IsNullOrWhiteSpace(Usuario.Nick))
{
Usuario.ErrorNick = true;
Usuario.MensajeErrorNick = "Apellidos, es obligatorio";
datosValidos = false;
}
else
{
Usuario.ErrorNick = false;
Usuario.MensajeErrorNick = "";
}
if (string.IsNullOrWhiteSpace(Usuario.Pass))
{
Usuario.ErrorPass = true;
Usuario.MensajeErrorPass = "Apellidos, es obligatorio";
datosValidos = false;
}
else
{
Usuario.ErrorPass = false;
Usuario.MensajeErrorPass = "";
}
return datosValidos;
}
private void AgregarHobbie()
{
if (!string.IsNullOrEmpty(nuevoHobbie))
{
MensajeErrorHobbie = "";
ErrorHobbie = false;
usuario.Hobbies.Add(new DtoHobbie { Nombre = nuevoHobbie });
NuevoHobbie = "";
}
else
{
MensajeErrorHobbie = "No agregaste un hobbie";
ErrorHobbie = true;
}
}
private void LlenarEstadosCiudades()
{
ListaEstados=new ObservableCollection
{
"Guanajuato","Guerrero","Hidalgo","Jalisco","México","Michoacán","Morelos","Nayarit","Nuevo León","Oaxaca","Puebla"
};
}
#endregion
#region Eventos INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnSetProperty(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
#endregion
}
}
El Dto de usuario que tendría las siguientes propiedades
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace XamarinAdvientoSyncfusion.Dtos
{
public class DtoUsuario: INotifyPropertyChanged
{
#region PropiedadesUsuario
private string estado;
public string Estado
{
get { return estado; }
set { estado = value; OnSetProperty("Estado"); }
}
private string nombre;
public string Nombre
{
get { return nombre; }
set { nombre = value; OnSetProperty("Nombre"); }
}
private string apellidos;
public string Apellidos
{
get { return apellidos; }
set { apellidos = value; OnSetProperty("Apellidos"); }
}
private string nick;
public string Nick
{
get { return nick; }
set { nick = value; OnSetProperty("Nick"); }
}
private string pass;
public string Pass
{
get { return pass; }
set { pass = value; OnSetProperty("Pass"); }
}
private ObservableCollection hobbies=new ObservableCollection();
public ObservableCollection Hobbies
{
get { return hobbies; }
set
{hobbies = value; OnSetProperty("Hobbies"); }
}
#endregion
#region ManejoDeErrores
private string mensajeErrorUsuario;
public string MensajeErrorUsuario
{
get { return mensajeErrorUsuario; }
set { mensajeErrorUsuario = value; OnSetProperty("MensajeErrorUsuario"); }
}
private bool errorUsuario;
public bool ErrorUsuario
{
get { return errorUsuario; }
set { errorUsuario = value; OnSetProperty("ErrorUsuario"); }
}
private string mensajeErrorApellidos;
public string MensajeErrorApellidos
{
get { return mensajeErrorUsuario; }
set { mensajeErrorUsuario = value; OnSetProperty("MensajeErrorApellidos"); }
}
private bool errorApellidos;
public bool ErrorApellidos
{
get { return errorApellidos; }
set { errorApellidos = value; OnSetProperty("ErrorApellidos"); }
}
private string mensajeErrorNick;
public string MensajeErrorNick
{
get { return mensajeErrorNick; }
set { mensajeErrorNick = value; OnSetProperty("MensajeErrorNick"); }
}
private bool errorNick;
public bool ErrorNick
{
get { return errorNick; }
set { errorNick = value; OnSetProperty("ErrorNick"); }
}
private string mensajeErrorPass;
public string MensajeErrorPass
{
get { return mensajeErrorPass; }
set { mensajeErrorPass = value; OnSetProperty("MensajeErrorPass"); }
}
private bool errorPass;
public bool ErrorPass
{
get { return errorPass; }
set { errorPass = value; OnSetProperty("ErrorPass"); }
}
#endregion
#region Eventos INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnSetProperty(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
#endregion
}
}
Ya para concluir, el resultado que podrás ver es algo parecido a esto
Todo este código lo podrás encontrar en mi repo de Git, así cerramos esta entrada espero que te sea útil la información. Cualquier duda puedes dejarla en el apartado de comentario, estaré pendiente si puedo ayudar en algo :)
Comentarios
Publicar un comentario
¡Tú! también puedes aportar con tu comentario