Search code examples
c#mvvmxamarin.formscontextmenudatatemplate

Xamarin.Forms - Binding on ContextMenu


I have a list with songs as items. A long press on the element should display a context menu.

AllSongsViewModel.xaml:

<DataTemplate x:Key="SongTemplate">
    <ViewCell>
        <ViewCell.ContextActions>
            <MenuItem Text="Edit" />
            <MenuItem Text="Delete"/>
        </ViewCell.ContextActions>

        <StackLayout Padding="15,5" VerticalOptions="Center">

            <Label Text="{Binding Title}"
                   FontSize="16"/>
            <Label Text="{Binding Performer}"
                   FontSize="12"/>
        </StackLayout>
    </ViewCell>
</DataTemplate>

This works well, but I need to bind now so that the context menu opens depending on bool IsAdmin, which lies in AllSongsViewModel

AllSongsViewModel.cs:

public bool IsAdmin => _authService.LoggedUser.Role == "Admin";

But I don’t know how to bind this property to the context menu


Solution

  • Unfortunately you can't do this on your ViewModel. But you can set a BindingContextChange event on your View Cell and change it there like this:

    XAML:

    <DataTemplate x:Key="SongTemplate">
     <ViewCell BindingContextChanged="OnBindingContextChanged">
        <StackLayout Padding="15,5" VerticalOptions="Center">
    
            <Label Text="{Binding Title}"
                   FontSize="16"/>
            <Label Text="{Binding Performer}"
                   FontSize="12"/>
        </StackLayout>
    </ViewCell>
    

    In your code behind:

     private void OnBindingContextChanged(object sender, EventArgs e)
        {
            base.OnBindingContextChanged();
    
            if (BindingContext == null)
                return;
    
            ViewCell theViewCell = ((ViewCell)sender);
            var viewModel = this.BindingContext.DataContext as AllSongsViewModel;
            theViewCell.ContextActions.Clear();
    
            if (viewModel.IsAdmin)
            {
                theViewCell.ContextActions.Add(new MenuItem()
                {
                    Text = "Delete",
                });
    
                theViewCell.ContextActions.Add(new MenuItem()
                {
                    Text = "Edit",
                });
            }
        }