Xamarin.Forms MenuItem
Xamarin.FormsMenuItem
类定义菜单的菜单项,例如 ListView
项上下文菜单和 Shell 应用程序浮出控件菜单。
以下屏幕截图显示了 iOS 和 Android 上的 ListView
上下文菜单中的 MenuItem
对象:
MenuItem
类定义以下属性:
Command
是一个ICommand
,允许将用户操作(如手指点击或单击)绑定到 viewmodel 上定义的命令。CommandParameter
是一个object
,用于指定应传递给Command
的参数。IconImageSource
是定义显示图标的ImageSource
值。IsDestructive
是指示MenuItem
是否从列表中删除其关联的 UI 元素的bool
值。IsEnabled
是指示此对象是否响应用户输入的bool
值。Text
是指定显示文本的string
值。
这些属性由 BindableProperty
对象提供支持,因此 MenuItem
实例可以是数据绑定的目标。
创建 MenuItem
MenuItem
对象可在 ListView
对象项的上下文菜单中使用。 最常见的模式是在 ViewCell
实例中创建 MenuItem
对象,该实例用作 ListView
ItemTemplate
的 DataTemplate
对象。 填充 ListView
对象时,它将使用 DataTemplate
创建每个项,并在为项激活上下文菜单时公开 MenuItem
选项。
以下示例演示 ListView
对象上下文中的 MenuItem
实例化:
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Context Menu Option" />
</ViewCell.ContextActions>
<Label Text="{Binding .}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
还可以在代码中创建 MenuItem
:
// 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
事件。 事件处理程序可以附加到此事件,以响应 XAML 中对 MenuItem
实例的点击或单击操作:
<MenuItem ...
Clicked="OnItemClicked" />
还可以在代码中附加事件处理程序:
MenuItem item = new MenuItem { ... }
item.Clicked += OnItemClicked;
前面的示例引用了 OnItemClicked
事件处理程序。 以下代码演示了一个示例实现:
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
}
使用 MVVM 定义 MenuItem 行为
MenuItem
类通过 BindableProperty
对象和 ICommand
接口支持模型-视图-视图模型 (MVVM) 模式。 以下 XAML 显示绑定到在 viewmodel 上定义的命令的 MenuItem
实例:
<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
属性绑定到 viewmodel 上的命令。 viewmodel 包含 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}";
});
}
示例应用程序包括一个 DataService
类,用于获取填充 ListView
对象的项列表。 viewmodel 已实例化,其项来自 DataService
类,并设置为代码隐藏的 BindingContext
:
public MenuItemXamlMvvmPage()
{
InitializeComponent();
BindingContext = new ListPageViewModel(DataService.GetListItems());
}
MenuItem 图标
警告
MenuItem
对象仅在 Android 上显示图标。 在其他平台上,将仅显示 Text
属性指定的文本。
使用 IconImageSource
属性指定图标。 如果指定了图标,则不会显示由 Text
属性指定的文本。 以下屏幕截图显示了 Android 上带有图标的 MenuItem
:
有关在 Xamarin.Forms 中使用图像的详细信息,请参阅 Xamarin.Forms 中的图像。
在运行时启用或禁用 MenuItem
若要在运行时启用或禁用 MenuItem
,请将其 Command
属性绑定到 ICommand
实现,并确保 canExecute
委托根据需要启用或禁用 ICommand
。
重要
使用 Command
属性启用或禁用 MenuItem
时,请勿将 IsEnabled
属性绑定到另一个属性。
以下示例演示了其 Command
属性绑定到 ICommand
(名为 MyCommand
)的 MenuItem
:
<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);
}
}
在此示例中,设置 IsMenuItemEnabled
属性之前一直禁用 MenuItem
。 发生这种情况时,将会调用 Command.ChangeCanExecute
方法,以便重新评估委托 MyCommand
的 canExecute
委托。
跨平台上下文菜单行为
上下文菜单在每个平台上以不同的方式进行访问和显示。
在 Android 上,通过长按列表项来激活上下文菜单。 上下文菜单可替换标题和导航栏区域,MenuItem
选项显示为水平按钮。
在 iOS 上,通过轻扫列表项来激活上下文菜单。 上下文菜单显示在列表项上,MenuItems
显示为水平按钮。
在 UWP 上,通过右键单击列表项来激活上下文菜单。 上下文菜单在光标附近显示为垂直列表。