Xamarin.Forms MenuItem
La clase Xamarin.FormsMenuItem
define elementos de menú para menús como menús contextuales de elementos ListView
y menús flotantes de aplicaciones de Shell.
En las capturas de pantalla siguientes se muestran objetos MenuItem
en un menú contextual ListView
en iOS y Android:
La clase MenuItem
define las propiedades siguientes:
Command
es unICommand
que permite enlazar acciones de usuario, como pulsaciones de dedo o clics, a los comandos definidos en un modelo de vista.CommandParameter
es un objetoobject
que especifica el parámetro que se debe pasar alCommand
.IconImageSource
es un valorImageSource
que define el icono de presentación.IsDestructive
es un valorbool
que indica si elMenuItem
quita su elemento de interfaz de usuario asociado de la lista.IsEnabled
es un valorbool
que indica si este objeto responde a la entrada del usuario.Text
es un valorstring
que especifica el texto para mostrar.
Estas propiedades están respaldadas por objetos BindableProperty
para que la instancia MenuItem
pueda ser el destino de los enlaces de datos.
Crear un objeto MenuItem
Los objetos MenuItem
se pueden usar en un menú contextual en los elementos de un objeto ListView
. El patrón más común es crear objetos MenuItem
dentro de una instancia ViewCell
, que se usa como objeto DataTemplate
para la ItemTemplate
de ListView
. Cuando se rellena el objeto ListView
, creará cada elemento usando DataTemplate
, exponiendo las opciones MenuItem
cuando se active el menú contextual para un elemento.
En el ejemplo siguiente se muestra creación de instancias MenuItem
dentro del contexto de un objeto ListView
:
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Context Menu Option" />
</ViewCell.ContextActions>
<Label Text="{Binding .}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
También se puede crear MenuItem
en código:
// A function returns a ViewCell instance that
// is used as the template for each list item
DataTemplate dataTemplate = new DataTemplate(() =>
{
// A Label displays the list item text
Label label = new Label();
label.SetBinding(Label.TextProperty, ".");
// A ViewCell serves as the DataTemplate
ViewCell viewCell = new ViewCell
{
View = label
};
// Add a MenuItem instance to the ContextActions
MenuItem menuItem = new MenuItem
{
Text = "Context Menu Option"
};
viewCell.ContextActions.Add(menuItem);
// The function returns the custom ViewCell
// to the DataTemplate constructor
return viewCell;
});
// Finally, the dataTemplate is provided to
// the ListView object
ListView listView = new ListView
{
...
ItemTemplate = dataTemplate
};
Definición del comportamiento MenuItem con eventos
La clase MenuItem
expone un evento Clicked
. Un controlador de eventos se puede adjuntar a este evento para reaccionar ante pulsaciones o clics en la instancia MenuItem
en XAML:
<MenuItem ...
Clicked="OnItemClicked" />
Un controlador de eventos también se puede adjuntar en el código:
MenuItem item = new MenuItem { ... }
item.Clicked += OnItemClicked;
En los ejemplos anteriores, se hace referencia a un controlador de eventos OnItemClicked
. En el siguiente código, se muestra un ejemplo de ejecución:
void OnItemClicked(object sender, EventArgs e)
{
// The sender is the menuItem
MenuItem menuItem = sender as MenuItem;
// Access the list item through the BindingContext
var contextItem = menuItem.BindingContext;
// Do something with the contextItem here
}
Definición del comportamiento MenuItem con MVVM
La clase MenuItem
admite el patrón Model-View-ViewModel (MVVM) a través de objetos BindableProperty
y la interfaz ICommand
. El siguiente código XAML muestra MenuItem
instancias enlazadas a comandos definidos en un modelo de vista:
<ContentPage.BindingContext>
<viewmodels:ListPageViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Label Text="{Binding Message}" ... />
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Edit"
IconImageSource="icon.png"
Command="{Binding Source={x:Reference contentPage}, Path=BindingContext.EditCommand}"
CommandParameter="{Binding .}"/>
<MenuItem Text="Delete"
Command="{Binding Source={x:Reference contentPage}, Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding .}"/>
</ViewCell.ContextActions>
<Label Text="{Binding .}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
En el ejemplo anterior, se definen dos objetos MenuItem
con sus propiedades Command
y CommandParameter
enlazadas a comandos en el modelo de vista. El modelo de vista contiene los comandos a los que se hace referencia en XAML:
public class ListPageViewModel : INotifyPropertyChanged
{
...
public ICommand EditCommand => new Command<string>((string item) =>
{
Message = $"Edit command was called on: {item}";
});
public ICommand DeleteCommand => new Command<string>((string item) =>
{
Message = $"Delete command was called on: {item}";
});
}
La aplicación de ejemplo incluye una clase DataService
usada para obtener una lista de elementos para rellenar los objetos ListView
. Se crea una instancia de un modelo de vista, con elementos de la clase DataService
y se establece como el BindingContext
en el código subyacente:
public MenuItemXamlMvvmPage()
{
InitializeComponent();
BindingContext = new ListPageViewModel(DataService.GetListItems());
}
Iconos MenuItem
Advertencia
Los objetos MenuItem
solo muestran iconos en Android. En otras plataformas, solo se mostrará el texto especificado por la propiedad Text
.
Los iconos se especifican mediante la propiedad IconImageSource
. Si se especifica un icono, no se mostrará el texto especificado por la propiedad Text
. En las capturas de pantalla siguientes se muestra un MenuItem
con un icono en iOS y Android:
Para obtener más información sobre el uso de imágenes en Xamarin.Forms, consulte Imágenes en Xamarin.Forms.
Habilitar o deshabilitar un objeto MenuItem en tiempo de ejecución
Para habilitar la deshabilitación de un MenuItem
en runtime, enlace su propiedad Command
a una implementación ICommand
y asegúrese de que un delegado canExecute
habilita y deshabilita el ICommand
según corresponda.
Importante
No enlace la propiedad IsEnabled
a otra propiedad al usar la propiedad Command
para habilitar o deshabilitar el MenuItem
.
En el siguiente ejemplo se muestra un MenuItem
cuya propiedad Command
se enlaza a un ICommand
denominado MyCommand
:
<MenuItem Text="My menu item"
Command="{Binding MyCommand}" />
La implementación ICommand
requiere un delegado canExecute
que devuelve el valor de una propiedad bool
para habilitar y deshabilitar el MenuItem
:
public class MyViewModel : INotifyPropertyChanged
{
bool isMenuItemEnabled = false;
public bool IsMenuItemEnabled
{
get { return isMenuItemEnabled; }
set
{
isMenuItemEnabled = value;
MyCommand.ChangeCanExecute();
}
}
public Command MyCommand { get; private set; }
public MyViewModel()
{
MyCommand = new Command(() =>
{
// Execute logic here
},
() => IsMenuItemEnabled);
}
}
En este ejemplo, el MenuItem
se deshabilita hasta que se establece la propiedad IsMenuItemEnabled
. Cuando esto ocurre, se llama al método Command.ChangeCanExecute
, lo que hace que el delegado canExecute
para MyCommand
se vuelva a evaluar.
Comportamiento del menú contextual multiplataforma
Se accede a los menús contextuales y se muestran de forma diferente en cada plataforma.
En Android, el menú contextual se activa presionando prolongadamente en un elemento de lista. El menú contextual reemplaza el área de título y barra de navegación y las opciones MenuItem
se muestran como botones horizontales.
En iOS, el menú contextual se activa deslizando el dedo en un elemento de lista. El menú contextual se muestra en el elemento de lista y MenuItems
se muestra como botones horizontales.
En UWP, el menú contextual se activa haciendo clic con el botón derecho en un elemento de lista. El menú contextual se muestra cerca del cursor como una lista vertical.