Xamarin.Forms MenuItem
Xamarin.FormsMenuItem
クラスは、ListView
項目のコンテキスト メニューやシェル アプリケーションのポップアップ メニューなどのメニューのメニュー項目を定義します。
次のスクリーンショットは、iOS と Android の ListView
コンテキスト メニューの MenuItem
オブジェクトを示しています。
MenuItem
クラスには、次のプロパティが定義されています。
Command
: 指のタップやクリックなどのユーザー アクションを、ビューモデルで定義されているコマンドにバインドできるようにするICommand
。CommandParameter
:Command
に渡すパラメーターを指定するobject
。IconImageSource
は、表示アイコンを定義するImageSource
値です。IsDestructive
は、MenuItem
が関連付けられている UI 要素をリストから削除するかどうかを示すbool
値です。IsEnabled
は、このオブジェクトがユーザーによる入力に応答するかどうかを示すbool
値です。Text
は、表示テキストを指定するstring
値です。
これらのプロパティは BindableProperty
オブジェクトによってサポートされるため、MenuItem
インスタンスをデータ バインディングの対象にすることができます。
MenuItem を作成する
MenuItem
オブジェクトは、ListView
オブジェクトの項目のコンテキスト メニュー内で使用できます。 最も一般的なパターンは、ViewCell
インスタンス内に MenuItem
オブジェクトを作成し、ListView
s 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
インターフェイスを介して Model-View-ViewModel (MVVM) パターンをサポートします。 次の XAML は、ビューモデルで定義されコマンドにバインドされた 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>
前の例では、ビューモデル上のコマンドにバインドされた Command
と CommandParameter
プロパティを使用して、2 つの MenuItem
オブジェクトが定義されています。 ビューモデルには、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}";
});
}
サンプル アプリケーションには、ListView
オブジェクトを設定するための項目の一覧を取得するために使用する DataService
クラスが含まれています。 ビューモデルは、DataService
クラスの項目を使用してインスタンス化され、コードビハインドで BindingContext
として設定されます。
public MenuItemXamlMvvmPage()
{
InitializeComponent();
BindingContext = new ListPageViewModel(DataService.GetListItems());
}
MenuItem アイコン
警告
Android では、MenuItem
オブジェクトはアイコンのみを表示します。 他のプラットフォームでは、Text
プロパティで指定されたテキストのみが表示されます。
アイコンは、IconImageSource
プロパティを使用して指定します。 アイコンを指定した場合、Text
プロパティで指定されたテキストは表示されません。 次のスクリーンショットは、Android でのアイコン付きの MenuItem
を示しています。
Xamarin.Forms でのイメージの使用の詳細については、「Xamarin.Forms での画像」を参照してください。
MenuItem を実行時に有効または無効にする
実行時に MenuItem
を無効にするには、その Command
プロパティを ICommand
実装にバインドし、canExecute
デリゲートが必要に応じて ICommand
を有効および無効にするようにします。
重要
Command
プロパティを使用して MenuItem
を有効または無効にする場合は、IsEnabled
プロパティを別のプロパティにバインドしないでください。
次の例は、Command
プロパティが MyCommand
という名前の ICommand
にバインドされる MenuItem
を示しています。
<MenuItem Text="My menu item"
Command="{Binding MyCommand}" />
ICommand
実装では、MenuItem
を有効または無効にする bool
プロパティの値を返す canExecute
デリゲートが必要です。
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 では、リスト アイテムを右クリックするとコンテキスト メニューがアクティブになります。 コンテキスト メニューは、カーソルの近くに垂直リストとして表示されます。