(带有 MVVM 的 Xamarin MasterPageDetail ListView SelectedItem)如何在单击时正确加载菜单页面?
(Xamarin MasterPageDetail ListView SelectedItem with MVVM) How to load menu page properly on click?
我不确定如何正确地将列表视图中的选定菜单项绑定到视图模型中其关联的加载页面事件。
我现在拥有的方式有效。 但是,问题是菜单页面保持选中状态(从左侧滑动菜单时仍然突出显示为橙色)并且如果再次单击侧面菜单不会消失并且没有任何反应,直到选择不同的页面. ( IPropertyChanged 如果单击相同的项目不会触发......或者它是否会触发并检查是否有更改并设置它?)
请问如何以正确的 MVVM 方式解决这个问题?
请注意照片中的最后一个选择保持选中状态,再次单击应该重新加载页面时没有任何反应。只有点击另一个页面才有效。
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>
我的视图模型:
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) });
}
}
我的基本视图模型Class:
public class BaseVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
最后是 MasterPageDetail 页面 CS:
public partial class MyMainPage : MasterDetailPage
{
private MyMainPageVM myMainPageVM;
public MyMainPage ()
{
InitializeComponent ();
myMainPageVM = new MyMainPageVM();
this.BindingContext = myMainPageVM
}
}
您必须设置 ListView.SelectedItem = null
以在导航到新页面时移除所选项目的高亮状态。
要访问 ListView
,首先,在 MasterDetailPage.xaml
中为 ListView
命名:
<ListView ItemsSource="{Binding MenuList}"
electedItem="{Binding MenuSelectedItem, Mode=TwoWay}"
RowHeight="45"
SeparatorVisibility="Default"
BackgroundColor="#e8e8e8"
x:Name="masterListView">
在后面的代码中,创建一个 public static ListView masterList
并设置 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;
}
}
然后,在navigate:
之后就可以访问其他class、Set the SelectedItem=null
中的listView了
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;
}
}
如果有效请告诉我。
我不确定如何正确地将列表视图中的选定菜单项绑定到视图模型中其关联的加载页面事件。
我现在拥有的方式有效。 但是,问题是菜单页面保持选中状态(从左侧滑动菜单时仍然突出显示为橙色)并且如果再次单击侧面菜单不会消失并且没有任何反应,直到选择不同的页面. ( IPropertyChanged 如果单击相同的项目不会触发......或者它是否会触发并检查是否有更改并设置它?)
请问如何以正确的 MVVM 方式解决这个问题?
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>
我的视图模型:
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) });
}
}
我的基本视图模型Class:
public class BaseVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
最后是 MasterPageDetail 页面 CS:
public partial class MyMainPage : MasterDetailPage
{
private MyMainPageVM myMainPageVM;
public MyMainPage ()
{
InitializeComponent ();
myMainPageVM = new MyMainPageVM();
this.BindingContext = myMainPageVM
}
}
您必须设置 ListView.SelectedItem = null
以在导航到新页面时移除所选项目的高亮状态。
要访问 ListView
,首先,在 MasterDetailPage.xaml
中为 ListView
命名:
<ListView ItemsSource="{Binding MenuList}"
electedItem="{Binding MenuSelectedItem, Mode=TwoWay}"
RowHeight="45"
SeparatorVisibility="Default"
BackgroundColor="#e8e8e8"
x:Name="masterListView">
在后面的代码中,创建一个 public static ListView masterList
并设置 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;
}
}
然后,在navigate:
之后就可以访问其他class、Set the SelectedItem=null
中的listView了
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;
}
}
如果有效请告诉我。