[How To] Establecer foco en XAML desde MVVM

[How To] Establecer foco en XAML desde MVVM

Introducci贸n

Cuando trabajamos con el patr贸n MVVM, no tenemos acceso directo a la interfaz de usuario, por lo tanto, establecer el foco de un control visual se complica un poco. En esta peque帽a entrada muestro como poder hacerlo. Simplemente utilizamos una propiedad para tal efecto 馃檪

Utilizando el c贸digo

Realizaremos los siguientes pasos para lograr nuestro objetivo:

  1. Creamos un Modelo que se llama Club.
  2. Creamos el ViewModel con una propiedad Foco, que enviar谩 las notificaciones a la Vista.
  3. En la Vista agregamos un Trigger al estilo.

Primero creamos nuestro modelo de esta manera:

public class Club
{
int orden;
public int Orden
{
get
{
return orden;
}
set
{
orden = value;
}
}

string nombre;
public string Nombre
{
get
{
return nombre;
}
set
{
nombre = value;
}
}
}

Ahora, procedemos a crear nuestro ViewModel tal como se demuestra a continuaci贸n:

public class ClubViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}

ObservableCollection clubes;
public ObservableCollection Clubes
{
get
{
if (clubes == null)
this.clubes = new ObservableCollection();
return this.clubes;
}
set
{
this.clubes = value;
OnPropertyChanged("Clubes");
}
}

public ClubViewModel()
{
var lista = new List();
lista.Add(new Club()
{
Orden = 1, Nombre = "Manchester United"
});
lista.Add(new Club()
{
Orden = 2, Nombre = "Liverpool"
});
lista.Add(new Club()
{
Orden = 3, Nombre = "Chelsea"
});
lista.Add(new Club()
{
Orden = 4, Nombre = "Manchester City"
});
lista.Add(new Club()
{
Orden = 5, Nombre = "Arsenal"
});

Clubes = new ObservableCollection(lista);
Foco = true;
}

bool foco_;
public bool Foco
{
get
{
return foco_;
}
set
{
foco_ = value;
OnPropertyChanged("Foco");
}
}
}

El XAML sin nuestro Trigger quedar铆a de la siguiente manera:


<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:datos="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<datos:ClubViewModel />
</Window.DataContext>

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<StackPanel Orientation="Horizontal">
<TextBlock Text="Filtro" Margin="2" />
<TextBox Name="texto" Margin="2" Text="{Binding ElementName=lista, Path=SelectedItem.Nombre}" />
</StackPanel>

<ListView Name="lista" Grid.Row="1" Margin="5" ItemsSource="{Binding Clubes}"
DisplayMemberPath="Nombre" SelectedValue="Orden" SelectedItem="{Binding Clubes[0]}" />
</Grid>
</Window>

Lo que debemos agregar a nuestro Grid es el Trigger correspondiente:


<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Foco}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=texto}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>

El XAML final quedar铆a de la siguiente manera:


<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:datos="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<datos:ClubViewModel />
</Window.DataContext>

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Foco}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=texto}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>

<StackPanel Orientation="Horizontal">
<TextBlock Text="Filtro" Margin="2" />
<TextBox Name="texto" Margin="2" Text="{Binding ElementName=lista, Path=SelectedItem.Nombre}" />
</StackPanel>

<ListView Name="lista" Grid.Row="1" Margin="5" ItemsSource="{Binding Clubes}"
DisplayMemberPath="Nombre" SelectedValue="Orden" SelectedItem="{Binding Clubes[0]}" />
</Grid>
</Window>

Conclusi贸n

De manera muy sencilla podemos colocar el foco en nuestro control mediante una propiedad que enlazamos al Trigger de un estilo.

Deja un comentario

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *

Este sitio usa Akismet para reducir el spam. Aprende c贸mo se procesan los datos de tus comentarios.