I am not sure how to properly bind a selected menu item from a listview to its associated load page event in the view model.
The way I have it right now it works. BUT, the problem is that a menu page stays selected(still highlighted orange when sliding menu from left) and if clicked again the side menu does not disappear and nothing happens, until selecting a different page. ( IPropertyChanged does not trigger if clicking same item...or does it trigger anyways and checks if there is a change and sets it or not?)
How to fix this please in the correct MVVM way?
Notice in the photo last selection stays selected, and clicking again nothing happens when it should reload the page. Only clicking another page works.
The MasterDetailPage:
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MyApp.Views"
x:Class="MyApp.Views.MyMainPage"
Title="My Main Page">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<ContentPage.Content>
<Grid BackgroundColor="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="130" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<Image Source="menu_background.png"
Aspect="AspectFill" />
<StackLayout Padding="0,20,0,0"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand">
<Image Source="ac_logo.png"
Aspect="AspectFit"
WidthRequest="60"
HeightRequest="60" />
<Label Text="myAC" TextColor="White" FontSize="Large" />
</StackLayout>
</Grid>
<StackLayout Grid.Row="1"
Spacing="15">
<ListView ItemsSource="{Binding MenuList}"
SelectedItem="{Binding MenuSelectedItem, Mode=TwoWay}"
RowHeight="45"
SeparatorVisibility="Default"
BackgroundColor="#e8e8e8">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<!-- Main design for our menu items -->
<StackLayout VerticalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="20,10,0,10"
Spacing="20">
<Image Source="{Binding IconSource}"
WidthRequest="30"
HeightRequest="30"
VerticalOptions="Center" />
<Label Text="{Binding Title}"
FontSize="Medium"
VerticalOptions="Center"
TextColor="Black"/>
</StackLayout>
<BoxView HeightRequest="1" BackgroundColor="Gray"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
</ContentPage.Content>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<views:StudentHomePage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
My ViewModel:
public class MyMainPageVM : BaseVM
{
public ObservableCollection<MenuPageItem> MenuList { get; set; }
private MenuPageItem _menuSelectedItem = null;
public MenuPageItem MenuSelectedItem
{
get
{
return _menuSelectedItem;
}
set
{
//if (_menuSelectedItem != value)
// {
_menuSelectedItem = value;
// navigate
(App.Current.MainPage as MasterDetailPage).Detail = new NavigationPage((Page)Activator.CreateInstance(_menuSelectedItem.TargetType));
(App.Current.MainPage as MasterDetailPage).IsPresented = false;
//}
}
}
public MyMainPageVM()
{
MenuList = new ObservableCollection<MenuPageItem>();
populateMenuList();
}
private void populateMenuList()
{
MenuList.Add(new MenuPageItem() { Title = "Home", IconSource = "home.png", TargetType = typeof(MyHomePage) });
MenuList.Add(new MenuPageItem() { Title = "Setting", IconSource = "setting.png", TargetType = typeof(Page2) });
MenuList.Add(new MenuPageItem() { Title = "Help", IconSource = "help.png", TargetType = typeof(Page3) });
}
}
My Base View Model Class:
public class BaseVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And finally the MasterPageDetail page CS:
public partial class MyMainPage : MasterDetailPage
{
private MyMainPageVM myMainPageVM;
public MyMainPage ()
{
InitializeComponent ();
myMainPageVM = new MyMainPageVM();
this.BindingContext = myMainPageVM
}
}
You have to set the ListView.SelectedItem = null
to remove the hightLight state of the selected item when navigating to a new page.
To accsess the ListView
, first, give the ListView
a name in your MasterDetailPage.xaml
:
<ListView ItemsSource="{Binding MenuList}"
electedItem="{Binding MenuSelectedItem, Mode=TwoWay}"
RowHeight="45"
SeparatorVisibility="Default"
BackgroundColor="#e8e8e8"
x:Name="masterListView">
In the code behind, create a public static ListView masterList
and set the masterList = masterListView
:
public partial class MyMainPage : MasterDetailPage
{
private MyMainPageVM myMainPageVM;
public static ListView masterList;
public MyMainPage ()
{
InitializeComponent();
myMainPageVM = new MyMainPageVM();
//bindingContext = myMainPageVM;
BindingContext = myMainPageVM;
//Set the masterList
masterList = masterListView;
}
}
Then, you can access the listView in other class, Set the SelectedItem=null
after navigate:
private MenuPageItem _menuSelectedItem = null;
public MenuPageItem MenuSelectedItem
{
get
{
return _menuSelectedItem;
}
set
{
_menuSelectedItem = value;
(App.Current.MainPage as MasterDetailPage).Detail = new NavigationPage((Page)Activator.CreateInstance(_menuSelectedItem.TargetType));
//Set the SelectedItem=null
MyMainPage.masterList.SelectedItem = null;
(App.Current.MainPage as MasterDetailPage).IsPresented = false;
}
}
Let me know if it works.