我使用了默认的Xamarin.Forms项目,并尝试使用Prism.Forms进行转换。
我设法通过App.xaml.cs中的MenuPage
在SplitView
和ItemsPage
的内容中显示NavigateAsync("MainPage/ItemsPage")
。
前进,我注意到导航到新页面时,没有在UWP应用上显示“返回”按钮,并且我读到我需要将MainPage
包装在NavigationPage
中,因此我尝试通过将NavigationPage
注册到容器和NavigateAsync("NavigationPage/MainPage/ItemsPage"),
来做到这一点,但不幸的是,我的UI空白。
我在这里做什么错了?
如果这还不够,我可以提供更多代码。
在App.xaml.cs中
protected override void OnInitialized()
{
this.InitializeComponent();
var navigationPage = $"{nameof(NavigationPage)}/{nameof(Views.MainPage)}/{nameof(ItemsPage)}"; // why does this shows blank UI?
var navigationPage2 = $"{nameof(Views.MainPage)}/{nameof(Views.ItemsPage)}"; // this shows MenuPage on the menu and items page on the main content.
_ = this.NavigationService.NavigateAsync($"{navigationPage}");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>(nameof(NavigationPage));
containerRegistry.RegisterForNavigation<AboutPage>(nameof(AboutPage));
containerRegistry.RegisterForNavigation<ItemDetailPage>(nameof(ItemDetailPage));
containerRegistry.RegisterForNavigation<ItemsPage>(nameof(ItemsPage));
containerRegistry.RegisterForNavigation<MainPage>(nameof(MainPage));
containerRegistry.RegisterForNavigation<MenuPage>(nameof(MenuPage));
containerRegistry.RegisterForNavigation<NewItemPage>(nameof(NewItemPage));
}
在MainPage.xaml中(这是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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:views="clr-namespace:XamarinApp.Views"
x:Class="XamarinApp.Views.MainPage">
<MasterDetailPage.Master>
<views:MenuPage />
</MasterDetailPage.Master>
</MasterDetailPage>
在MenuPage.xaml
中<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:b="clr-namespace:XamarinApp.Behaviors"
xmlns:prism="http://prismlibrary.com"
mc:Ignorable="d"
x:Class="XamarinApp.Views.MenuPage"
prism:ViewModelLocator.AutowireViewModel="True"
Title="Menu">
<StackLayout VerticalOptions="FillAndExpand">
<ListView
x:Name="ListViewMenu"
HasUnevenRows="True"
ItemsSource="{Binding MenuItems, Mode=OneTime}"
SelectedItem="{Binding SelectedMenuItem, Mode=TwoWay}">
<ListView.Behaviors>
<b:EventToCommandBehavior
EventName="ItemSelected"
Command="{Binding ItemSelectedCommand, Mode=OneTime}"/>
</ListView.Behaviors>
<d:ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
</x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Label Text="{Binding Title}" d:Text="{Binding .}" FontSize="20"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
在ItemsPage.xaml中(虽然不相关)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:b="clr-namespace:XamarinApp.Behaviors"
xmlns:prism="http://prismlibrary.com"
mc:Ignorable="d"
x:Class="XamarinApp.Views.ItemsPage"
Title="{Binding Title}"
x:Name="BrowseItemsPage"
prism:ViewModelLocator.AutowireViewModel="True">
<ContentPage.Behaviors>
<b:EventToCommandBehavior
EventName="Appearing"
Command="{Binding LoadItemsCommand, Mode=OneTime}"/>
</ContentPage.Behaviors>
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Command="{Binding AddItemCommand, Mode=OneTime}"/>
</ContentPage.ToolbarItems>
<StackLayout Grid.Row="1">
<ListView
x:Name="ItemsListView"
ItemsSource="{Binding Items, Mode=OneWay}"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand, Mode=OneTime}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement">
<ListView.Behaviors>
<b:EventToCommandBehavior
EventName="ItemSelected"
Command="{Binding OnItemSelectedCommand, Mode=OneTime}"/>
</ListView.Behaviors>
<d:ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>First Item</x:String>
<x:String>Second Item</x:String>
<x:String>Third Item</x:String>
<x:String>Forth Item</x:String>
<x:String>Fifth Item</x:String>
<x:String>Sixth Item</x:String>
</x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding Text}"
d:Text="{Binding .}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="{Binding Description}"
d:Text="Item descripton"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
在ItemsPageViewModel.cs
private readonly INavigationService navigationService;
private ObservableCollection<Item> items;
private Item selectedItem;
public ItemsPageViewModel()
{
this.Title = "Browse";
this.Items = new ObservableCollection<Item>();
this.LoadItemsCommand = new DelegateCommand(this.LoadItems, this.CanLoadItems).ObservesProperty(() => this.Items);
this.OnItemSelectedCommand = new DelegateCommand(this.OnItemsSelected_Execute, this.OnItemsSelected_CanExecute).ObservesProperty(() => this.SelectedItem);
this.AddItemCommand = new DelegateCommand(this.AddItem);
}
public ItemsPageViewModel(INavigationService navigationService)
: this()
{
this.navigationService = navigationService;
}
public ObservableCollection<Item> Items
{
get => this.items;
set => this.SetProperty(ref this.items, value);
}
public Item SelectedItem
{
get => this.selectedItem;
set => this.SetProperty(ref this.selectedItem, value);
}
public ICommand AddItemCommand { get; }
public ICommand OnItemSelectedCommand { get; }
public ICommand LoadItemsCommand { get; }
private bool CanLoadItems()
{
return !(this.Items?.Any() ?? false);
}
private async void LoadItems()
{
if (this.IsBusy)
{
return;
}
this.IsBusy = true;
try
{
this.Items.Clear();
var items = await this.DataStore.GetItemsAsync(true);
foreach (var item in items)
{
this.Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
this.IsBusy = false;
}
}
private bool OnItemsSelected_CanExecute()
{
return this.SelectedItem != null;
}
private async void OnItemsSelected_Execute()
{
var parameters = new NavigationParameters
{
{ "hash", this.selectedItem.ToString() },
};
await this.navigationService.NavigateAsync($"{nameof(ItemDetailPage)}", parameters);
// When I navigated to the ItemDetailPage, I do not see the (SplitView/HamburgerMenu) PageMenu
// and I do not see Back button
// Manually deselect item.
this.SelectedItem = null;
}
private async void AddItem()
{
await this.navigationService.NavigateAsync($"{nameof(NewItemPage)}");
}
答案 0 :(得分:0)
我找到了答案:
在App.xaml.cs中
var navigationPage = $"{nameof(Views.MainPage)}/{nameof(NavigationPage)}/{nameof(ItemsPage)}";
_ = this.NavigationService.NavigateAsync($"{navigationPage}");
在ItemsPageViewModel.cs
// keep this code intact from example above to navigate, have a back button on the new page, and also keep the hamburger menu intact.
await this.navigationService.NavigateAsync($"{nameof(ItemDetailPage)}", parameters);
在MenuPageViewModel.cs
private async void ItemSelectedHandler()
{
if (this.SelectedMenuItem == null)
{
return;
}
var id = this.SelectedMenuItem.Id;
switch (id)
{
case MenuItemType.Browse:
// re-show the MenuPage in HamburgerMenu and wrap ItemsPage in NavigationPage.
// However, navigating with this method will not show the back button in the new page.
await this.navigationService.NavigateAsync($"/{nameof(MainPage)}/{nameof(NavigationPage)}/{nameof(ItemsPage)}");
break;
case MenuItemType.About:
// re-show the MenuPage in HamburgerMenu and wrap ItemsPage in NavigationPage.
// However, navigating with this method will not show the back button in the new page.
await this.navigationService.NavigateAsync($"/{nameof(MainPage)}/{nameof(NavigationPage)}/{nameof(AboutPage)}");
break;
}
}