Класс Xamarin.Forms MenuItem определяет элементы для контекстных меню элементов ListView и всплывающих меню для приложений Shell.
На следующих скриншотах показаны объекты MenuItem в контекстном меню ListView на iOS и Android:
Класс MenuItem определяет следующие свойства:
- Command – ICommand, позволяющий привязывать действия пользователя, такие как касания пальцем или щелчки, к командам, определенным на вью-модели.
- CommandParameter – объект, определяющий параметр, который должен быть передан команде.
- IconImageSource – значение ImageSource, определяющее иконку дисплея.
- IsDestructive – bool-значение, указывающее, удаляет ли данный MenuItem связанный с ним элемент пользовательского интерфейса из списка.
- IsEnabled – bool-значение, указывающее, реагирует ли данный объект на ввод пользователя.
- Text – строковое значение, задающее текст отображения.
Эти свойства поддерживаются объектами BindableProperty, поэтому экземпляр MenuItem может быть объектом привязки данных.
Создание MenuItem
Объекты MenuItem могут использоваться в контекстном меню Xamarin для элементов объекта ListView. Чаще всего такие объекты создаются в экземпляре ViewCell, который используется в качестве объекта DataTemplate для шаблона элементов ListView. Когда объект ListView заполняется, он создает каждый элемент с использованием шаблона DataTemplate, раскрывая возможности выбора MenuItem при активации контекстного меню для элемента.
Следующий пример показывает реализацию MenuItem в контексте объекта ListView:
<ListView> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ViewCell.ContextActions> <MenuItem Text="Context Menu Option" /> </ViewCell.ContextActions> <Label Text="{Binding .}" /> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
MenuItem также может быть создан в коде:
C#
// 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 };
Определение поведения MenuItem с помощью событий
Класс MenuItem предоставляет событие Clicked. К этому событию может быть присоединен хэндлер, реагирующий на нажатия или клики на элемент MenuItem в XAML:
<MenuItem ...
Clicked="OnItemClicked" />
Обработчик события также может быть вложен в код:
C#
MenuItem item = new MenuItem { ... } item.Clicked += OnItemClicked;
В предыдущих примерах упоминался обработчик события OnItemClicked. В следующем коде показан пример его реализации:
C#
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 }
Определение поведения MenuItem с помощью MVVM
Класс MenuItem поддерживает паттерн Model-View-ViewModel (MVVM) с помощью объектов BindableProperty и интерфейса ICommand. Следующий XAML показывает экземпляры MenuItem, привязанные к командам, определенным на ViewModel:
<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>
В предыдущем примере определены два объекта MenuItem, свойства которых Command и CommandParameter привязаны к командам на модели представления. Модель представления содержит команды, на которые ссылается XAML:
public class ListPageViewModel : INotifyPropertyChanged { ... public ICommand EditCommand => new Command((string item) => { Message = $"Edit command was called on: {item}"; }); public ICommand DeleteCommand => new Command((string item) => { Message = $"Delete command was called on: {item}"; }); }
Пример приложения включает класс DataService, который используется для получения списка элементов для заполнения объектов ListView. Реализуется ViewModel с элементами из класса DataService и устанавливается в качестве BindingContext в код:
public MenuItemXamlMvvmPage() { InitializeComponent(); BindingContext = new ListPageViewModel(DataService.GetListItems()); }
Иконки MenuItem
Предупреждение. Объекты MenuItem отображают значки только на Android. На других платформах будет отображаться только текст, заданный свойством Text.
Иконки указываются с помощью свойства IconImageSource. Если задан значок, то текст, указанный в свойстве Text, отображаться не будет. На следующем снимке экрана показан MenuItem с иконкой на Android:
Включение и отключение пункта меню во время выполнения программы
Чтобы включить или выключить элемент меню во время выполнения, привяжите его свойство Command к реализации ICommand и убедитесь, что canExecute включает и выключает ICommand в зависимости от ситуации.
Важно. Не связывайте свойство IsEnabled с другим свойством при использовании свойства Command для включения или выключения MenuItem.
В следующем примере показан MenuItem, свойство Command которого связывается с ICommand с именем MyCommand:
<MenuItem Text="My menu item"
Command="{Binding MyCommand}" />
Реализация ICommand требует наличия делегата canExecute, который возвращает значение свойства bool для включения и выключения 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); } }
В данном примере элемент MenuItem отключен до тех пор, пока не будет установлено свойство IsMenuItemEnabled. Когда это происходит, вызывается метод Command.ChangeCanExecute, который приводит к переоценке делегата canExecute для MyCommand.
Кроссплатформенное поведение контекстного меню
Доступ к контекстному меню и его отображение на каждой платформе осуществляется по-разному.
На Android контекстное меню активируется долгим нажатием на элемент списка. Контекстное меню заменяет область заголовка и навигационной панели, а опции MenuItem отображаются в виде горизонтальных кнопок.
В iOS контекстное меню активируется при проведении пальцем по элементу списка. Контекстное меню отображается на элементе списка, а MenuItems отображаются в виде горизонтальных кнопок.
В UWP контекстное меню активируется щелчком правой кнопки мыши на элементе списка. Контекстное меню отображается рядом с курсором в виде вертикального списка.