Side Menu - Xamarin Forms

0

I am creating a project in Xamarin.Forms who implements a side menu ( Master/Detail ). So far I have been able to display the menu correctly and list some items in it, the idea is to click on one of these menu items to open another page and here is where my problem is.

Since I am using MVVM template, my View is binding with a ViewModel , when I select one of the menu items it generates a exception that I can not solve.

I'll show the code to make it clearer:

View:

<StackLayout>
    <ListView x:Name="listaEmpresas" 
              ItemsSource="{Binding ListaMenu}" 
              SelectedItem="{Binding ItemSelecionado}">
        <ListView.Header>
            <StackLayout BackgroundColor="Gray" 
                         WidthRequest="100"  
                         HeightRequest="40">
                <Label Text="Menu de Navegação" 
                       TextColor="White" FontSize="18"
                       VerticalOptions="CenterAndExpand" 
                       HorizontalOptions="Center"/>
            </StackLayout>
        </ListView.Header>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <ViewCell.View>
                        <StackLayout>
                            <Label Text="{Binding Nome}" 
                                   FontSize="15"
                                   VerticalOptions="CenterAndExpand"
                                   HorizontalOptions="CenterAndExpand"/>
                        </StackLayout>
                    </ViewCell.View>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

Code Behind:

public partial class MasterView : ContentPage
{
    public MasterViewModel ViewModel { get; set; }

    public MasterView (ItensMenu menu)
    {
        InitializeComponent ();
        this.ViewModel = new MasterViewModel();
        this.BindingContext = this.ViewModel;
     }

    protected async override void OnAppearing()
    {
        base.OnAppearing();

        MessagingCenter.Subscribe<ItensMenu>(this, "ItemSelecionadoMenu",
            (msg) =>
            {
                Navigation.PushAsync(new VeiculoView());
                App.MasterDetail.Detail.Navigation.PushAsync(new VeiculoView());
            }); 
    }

ViewModel:

public class MasterViewModel : BaseViewModel
{
    public string teste { set; get; }
    public List<ItensMenu> ListaMenu { get; set; }

    public MasterViewModel()
    {
        this.teste = "Teste";
        this.ListaMenu = new List<ItensMenu>
        {
            new ItensMenu {Nome = "Creditos", Id = "1" },
            new ItensMenu {Nome = "Editar Perfil", Id = "2"},
            new ItensMenu {Nome = "Veiculos", Id = "3"},
            new ItensMenu {Nome = "Historico", Id = "4"},
            new ItensMenu {Nome = "Alertas", Id = "5"}
        };
    }

    private ItensMenu itemSelecionado;

    //Pegar o valor do item Selcionado do Menu
    public ItensMenu ItemSelecionado
    {
        get
        {
            return itemSelecionado;
        }
        set
        {
            itemSelecionado = value;

            if (value != null)
            {
                MessagingCenter.Send<ItensMenu>(itemSelecionado, "ItemSelecionadoMenu");
            }
        }
    }
}

When I click on one of the items the following exception occurs:

  

Unhandled Exception:

     

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. occurred

One detail is that when I change the code Navigation.Async by a DisplayAlert in CodeBehind it works normal.

    
asked by anonymous 27.06.2018 / 17:35

1 answer

0

I'll leave some snippets of code for you to try to replicate in your application, if you have any questions I'm available.

--------- MasterDetailView ------------ View

Note: Change the snippets of code that I tell you.

Change x: Class to the name of your class.

Change xmlns: pages to the path name of your Views.

Swap pages: MenuLateralView for the name of your Side View menu.

Swap pages: CheckInMenuView for the name of your View that will be the home page of your application.

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  x:Class="YesShowroom.Views.MasterDetailView"
                  xmlns:pages="clr-namespace:YesShowroom.Views">
<MasterDetailPage.Master>
    <pages:MenuLateralView x:Name="MasterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
    <NavigationPage>
        <x:Arguments>
            <pages:CheckInMenuView />
        </x:Arguments>
    </NavigationPage>
</MasterDetailPage.Detail>

--------- MasterDetailView ------------ Code Behind

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MasterDetailView : MasterDetailPage
{
    public MasterDetailView()
    {
        InitializeComponent();

        MasterPage.ListView.ItemSelected += ListView_ItemSelected;
        NavigationPage.SetHasNavigationBar(this, false);
    }

    private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as MenuItemModel;

        if (item == null)
            return;

        var page = (Page)Activator.CreateInstance(item.TargetType);
        page.Title = item.Title;

        Detail = new NavigationPage(page);
        IsPresented = false;

        MasterPage.ListView.SelectedItem = null;
    }
}

--------- Class MenuItemModel ------------

public class MenuItemModel
{
    public MenuItemModel()
    {
        TargetType = typeof(MasterDetailViewDetail);
    }

    public int Id { get; set; }
    public string Title { get; set; }

    public Type TargetType { get; set; }
}

--------- MasterDetailViewDetail ------------ View

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YesShowroom.Views.MasterDetailViewDetail"
             Title="Detail">
  <StackLayout Padding="10">
    <Label Text="Detail"/>
  </StackLayout>
</ContentPage>

--------- MasterDetailViewDetail ------------ Code Behind

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MasterDetailViewDetail : ContentPage
{
    public MasterDetailViewDetail()
    {
        InitializeComponent();
    }
}

--------- MenuLateralView ------------ View

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YesShowroom.Views.MenuLateralView"
             Title="Master">
  <StackLayout>
    <ListView x:Name="MenuItemsListView"
              SeparatorVisibility="None"
              HasUnevenRows="true"
              ItemsSource="{Binding MenuItems}">
      <ListView.Header>
        <Grid BackgroundColor="#16335a">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="10"/>
          </Grid.ColumnDefinitions>

         <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="80"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="10"/>
         </Grid.RowDefinitions>

          <Label Grid.Column="1"
                 Grid.Row="2"
                 Text="Yes Showroom"
                 TextColor="White"
                 FontSize="28"/>
         </Grid>
      </ListView.Header>
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <StackLayout Padding="15,10" HorizontalOptions="FillAndExpand">
              <Label VerticalOptions="FillAndExpand" 
                     VerticalTextAlignment="Center" 
                     Text="{Binding Title}" 
                     FontSize="24"/>
            </StackLayout>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </StackLayout>
</ContentPage>

--------- MenuLateralView ------------ Code Behind

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuLateralView : ContentPage
{
    public ListView ListView;

    public MenuLateralView()
    {
        InitializeComponent();

        BindingContext = new MenuLateralViewModel();
        ListView = MenuItemsListView;
    }

    class MenuLateralViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<MenuItemModel> MenuItems { get; set; }

        public MenuLateralViewModel()
        {
            MenuItems = new ObservableCollection<MenuItemModel>(new[]
            {
                new MenuItemModel { Id = 0, Title = "Check In", TargetType = typeof(CheckInMenuView) },
                new MenuItemModel { Id = 1, Title = "Status", TargetType = typeof(StatusView) },
                new MenuItemModel { Id = 3, Title = "Relatório", TargetType = typeof(RelatorioView) },
                new MenuItemModel { Id = 2, Title = "Sair", TargetType = typeof(LoginView) }
            });
        }

        #region INotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged == null)
                return;

            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}
    
30.06.2018 / 21:14