MVVM: Portabilidad en aplicaciones XAML

Preview:

DESCRIPTION

Presentación del patrón MVVM para crear aplicaciones portables.

Citation preview

Separar lógica de interfaz de usuario y la aplicación utilizando el patrón de MVVM

Compartir funcionalidad utilizando bibliotecas de clases de portables

Compartir código con Archivos Enlazados

Manejo de las diferencias de plataforma de Windows Phone y Windows 8

Compartir utilizando componentes Windows Runtime

User Interface

App Logic

General Model-View-ViewModel (MVVM)

Model

View

ViewModel

Data BindingsOne way

One time

Two way

Commands

Interfaz de Usuario

Clases con solo propiedades querepresentan las fuentes de los datos (archivos, servicios, bases de datos)

Estructuras querepresentan los contextosde datos de las pantallas y el que permiten el accesoa la logica de negocio

Aplicaciones de escritorio, web forms

Caja de texto

Etiqueta

Form.cs (Code behind C#)

Form.designer.cs (C#)

Clase

Form

Usar code behind en clases parciales,

es el escenario “típico o más sencillo”

de un desarrollador .NET.

Aplicaciones XAML

Caja de texto

Etiqueta

MainPage.xaml

(Lenguaje declarativo XAML)

MainPage.xaml.cs (Code behind C#)

Clase

MainPage

Nuestra meta para

hacer código portable

es usar code hind al

mínimo posible. En la

demo de hecho cero

code behind.

Usando XAML se pueden crear de forma declarativa los mismos elementos gráficos que se crearían en código

<StackPanel><TextBox/><Button/>

</StackPanel>

StackPanel stackPanel = new StackPanel();

TextBox textBox = new TextBox();stackPanel.Children.Add(textBox);

Button button = new Button();stackPanel.Children.Add(button);

Ambos escenarios permiten acceder a los controles de la pantalla como miembros de la clase que los contiene es decir

this.txtMensaje.Text = “Hola”;

Y crear event handlers para poner el código relacionado a una interacción del usuario, por ejemplo el click de un botón

private void Button_Click(object sender, RoutedEventArgs e) { //Code }

Sin embargo como ya lo dijimos, está no es la mejor práctica para hacer código portable y reusable.

Nombre

Editar perfil

Apellido

12:38

recordar

*****

iniciar sesión

password

soreygarcia

usuario

Text={Binding alias}

Password={Binding password}

Command={Binding IniciarSesionCommand}

DataContext={Binding Path=Usuario, Source={StaticResource Locator}}

<StackPanel x:Name="ContentPanel" Margin="12,0,12,0" Grid.Row="1" >

<TextBlock TextWrapping="Wrap" Text="TextBlock"/>

<TextBox Height="72" TextWrapping="Wrap" Text="TextBox"/>

<TextBlock TextWrapping="Wrap" Text="TextBlock"/>

<TextBox Height="72" TextWrapping="Wrap" Text="TextBox"/>

<Button Content="Button"/>

</StackPanel>

<StackPanel x:Name="ContentPanel" Margin="12,0,12,0" Grid.Row="1">

<TextBlock TextWrapping="Wrap" Text="TextBlock"/>

<TextBox Height="72" TextWrapping="Wrap" Text="{Binding Nombre, Mode=TwoWay}"/>

<TextBlock TextWrapping="Wrap" Text="TextBlock"/>

<TextBox Height="72" TextWrapping="Wrap" Text="{Binding Apellido, Mode=TwoWay}"/>

<Button Content="Button"/>

</StackPanel>

<Grid x:Name="LayoutRoot" Background="Transparent"

d:DataContext="{Binding Path=Persona, Source={StaticResource SampleDataSource}}">

<Grid x:Name="ContentPanel">

<!– Aquí van los demás elementos de nuestra vista -->

</Grid>

</Grid>

class Models

Player

«property»

+ Clues(): List<string>

+ Id(): int

+ Name(): string

+ Photo(): string

Esta clase es suficiente

para serializar el archivo

que tenemos

class ViewModels

ClueViewModel

«property»

+ Name(): string

+ Value(): string

BindableBase

MainViewModel

- jsonService: IJsonService

- navigationService: INavigationService

- phoneService: IPhoneService

- randomGen: Random

- LoadPlayers(): void

+ MainViewModel(INavigationService, IPhoneService)

~ SufflePlayers(): void

«property»

+ Players(): ObservableCollection<PlayerViewModel>

+ SelectedPlayer(): PlayerViewModel

BindableBase

PlayerViewModel

- navigationService: INavigationService

- phoneService: IPhoneService

- wasDiscovered: bool

- Discover(): void

- Guess(): void

+ PlayerViewModel(INavigationService, IPhoneService)

«property»

+ Answer(): string

+ Clues(): ObservableCollection<ClueViewModel>

+ DiscoverCommand(): ICommand

+ GuessCommand(): ICommand

+ Id(): int

+ Name(): string

+ ParentViewModel(): MainViewModel

+ Photo(): string

+ WasDiscovered(): bool

public class ItemViewModel : INotifyPropertyChanged{

private string lineOne;public string LineOne{

get { return lineOne; }set {

if (value != lineOne){lineOne = value;NotifyPropertyChanged("LineOne");

}}

}

public event PropertyChangedEventHandler PropertyChanged;private void NotifyPropertyChanged(String propertyName){

if (null != PropertyChanged) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

}}

public class MainViewModel : BindableBase

{

private String nombre;

public String Nombre

{

get

{

return this.nombre;

}

set

{

nombre = value;RaisePropertyChanged(“Nombre”);

}

}

private static HueClientViewModel hueClientVM = null;public static HueClientViewModel HueClientVM{

get{if (hueClientVM == null)

hueClientVM = new HueClientViewModel();return hueClientVM;

}}

public HueClientView(){

InitializeComponent();this.DataContext = App.HueClientVM;

}

<Application x:Class="Hue_Demo_Phone.App“ ...xmlns:vm="clr-namespace:Hue_Demo_Phone.ViewModels">

<Application.Resources><vm:HueClientViewModel x:Key="HueClientVM" />

</Application.Resources>

<phone:PhoneApplicationPage ..."DataContext="{StaticResource HueClientVM}">

<phone:PhoneApplicationPage><!-- XAML --><phone:PhoneApplicationPage.DataContext>

<Binding Path="Main" Source="{StaticResource Locator}"/></phone:PhoneApplicationPage.DataContext>

<Grid x:Name="LayoutRoot" Background="Transparent" >

</Grid>

EventsEvent

Handlers

Commanding

<StackPanel x:Name="ContentPanel" Margin="12,0,12,0" Grid.Row="1" >

<TextBlock TextWrapping="Wrap" Text="TextBlock"/>

<TextBox Height="72" TextWrapping="Wrap" Text="{Binding Nombre, Mode=TwoWay}"/>

<TextBlock TextWrapping="Wrap" Text="TextBlock"/>

<TextBox Height="72" TextWrapping="Wrap" Text="{Binding Apellido, Mode=TwoWay}"/>

<Button Content="Button" Command="{Binding GuardarPerfilCommand}"/>

</StackPanel>

<Button Content="Press this" Height="72" Margin="90,464,0,0" Name="button1" Width="300"Command="{Binding HelloCommand}"/>

<ListBox Height="100" x:Name="listBox1" ><i:Interaction.Triggers>

<i:EventTrigger EventName="SelectionChanged"><i:InvokeCommandAction Command="{Binding SelectionChanged}"

CommandParameter="{Binding ElementName=listBox1, Path=SelectedIndex}"/></i:EventTrigger>

</i:Interaction.Triggers></ListBox>

public ICommand GuardarPerfilCommand

{

get { return new RelayCommand(GuardarPerfil, null);}

}

private async void GuardarPerfil()

{

//Code

}

#endregion GuardarPerfil

class StickerBook

StickerBook.Logic

+ Common

+ Contracts

+ Models

+ Services

+ ViewModels

StickerBook.WinPhone

+ App

+ Common

+ Converters

+ Pages

+ Properties

+ SampleData

+ Services

StickerBook.WinRT

+ App

+ Common

+ Converters

+ Pages

+ Properties

+ SampleData

+ Services

http://aka.ms/ShareCode

Recommended