XAML WinUI NavigationView -如何在Frame中显示页面

5fjcxozz  于 2023-04-09  发布在  其他
关注(0)|答案(1)|浏览(189)

我正在构建一个无线电应用程序,其中包含NavigationView与一个页面(现在),这将是ExploreCountriesPage,但我有问题实现这一点。MainWindow.xaml是主窗口,真正应该处理导航,并应显示在frame元素的子页面的内容。不幸的是,当我试图在MainWindow.xaml的框架中显示ExploreCountriesPage时,我得到Object reference not set to an instance of an object错误。
最终,我想实现的是在主窗口的框架内显示页面,并在页面显示时立即获取数据。
我怎么才能做到这一点?我做错了什么?

App.cs

public partial class App : Application
    {
        public IServiceProvider Container { get; private set; }
        public App()
        {
            this.InitializeComponent();
        }

        private IServiceProvider RegisterServices()
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton<IRadioBrowserClient>(new RadioBrowserClient(apiUrl: "de1.api.radio-browser.info"));
            serviceCollection.AddSingleton<ExploreCountriesViewModel>();

            return serviceCollection.BuildServiceProvider();
        }
        protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
        {
            Container = RegisterServices();
            
            m_window = new MainWindow();
            m_window.Activate();
        }

        private Window m_window;
    }

MainWindow.cs

public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
            ContentFrame.Navigate(typeof(ExploreCountriesPage)); // <-- this line causes the error
        }
    }

MainWindow.xaml

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="Rad.io.Client.WinUI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Rad.io.Client.WinUI"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:views="using:Rad.io.Client.WinUI.Views">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Grid x:Name="AppTitleBar">
            <Image Source="Images/WindowIcon.png"
                   HorizontalAlignment="Left" 
                   Width="16" Height="16" 
                   Margin="8,0"/>
            <TextBlock x:Name="AppTitleTextBlock" Text="Rad.io"
                       TextWrapping="NoWrap"
                       Style="{StaticResource CaptionTextBlockStyle}" 
                       VerticalAlignment="Center"
                       Margin="28,0,0,0"/>
        </Grid>

        <NavigationView x:Name="NavigationView" 
                        SelectionChanged="NavigationView_SelectionChanged"
                        Header="Explore"
                        Grid.Row="1"
                        IsBackButtonVisible="Collapsed"
                        IsSettingsVisible="True">
            <NavigationView.MenuItems>
                <NavigationViewItem Icon="Globe" Content="Explore" Tag="Explore" />
                <NavigationViewItem Icon="Library" Content="Library" Tag="SamplePage2" />
                <NavigationViewItem Icon="Play" Content="Now Playing" Tag="SamplePage3" />
            </NavigationView.MenuItems>
            <Frame x:Name="ContentFrame"/>

        </NavigationView>
    </Grid>
</Window>

ExploreCountriesViewModel.cs

namespace Rad.io.Client.WinUI.ViewModels
{
    public class ExploreCountriesViewModel : INotifyPropertyChanged
    {
        private readonly IRadioBrowserClient radioBrowserClient;
        private List<NameAndCount> _countries;
        private List<NameAndCount> filteredCountries;
        private string entryQuery;

        public List<NameAndCount> Countries
        {
            get => _countries;
            set
            {
                _countries = value;
                RaisePropertyChanged();
            }
        }
        public List<NameAndCount> FilteredCountries
        {
            get
            {
                if (EntryQuery is null) return Countries;
                return Countries.Where(value => value.Name.Contains(EntryQuery, StringComparison.OrdinalIgnoreCase)).ToList();
            }
        }

        public string EntryQuery
        {
            get => entryQuery;
            set
            {
                entryQuery = value;
                RaisePropertyChanged();
            }
        }

        public ExploreCountriesViewModel(IRadioBrowserClient radioBrowserClient)
        {
            this.radioBrowserClient = radioBrowserClient;

            InitializeDataAsync();
        }

        public async Task InitializeDataAsync()
        {
            try
            {
                Countries = await radioBrowserClient.Lists.GetCountriesAsync();
                foreach (var result in Countries)
                {
                    Debug.WriteLine(result.Name);
                }

            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

ExploreCountriesPage.cs

public sealed partial class ExploreCountriesPage : Page
    {
        public ExploreCountriesViewModel CountriesViewModel { get; set; }
        public ExploreCountriesPage(ExploreCountriesViewModel exploreCountriesViewModel)
        {
            this.InitializeComponent();
            this.CountriesViewModel = exploreCountriesViewModel;
            DataContext = CountriesViewModel;
        }
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

               await CountriesViewModel.InitializeDataAsync();
        }

    }

ExploreCountriesPage.xaml

<Page
    x:Class="Rad.io.Client.WinUI.Views.ExploreCountriesPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Rad.io.Client.WinUI.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <StackPanel>
        <TextBlock Text="Content" 
                           Style="{ThemeResource TitleTextBlockStyle}"
                           Margin="32,0,0,0"/>
        <ListView BorderThickness="1"
                  ItemsSource="{x:Bind CountriesViewModel.FilteredCountries}"
                  BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
                  VerticalAlignment="Stretch"
                  HorizontalAlignment="Stretch"/>

    </StackPanel>
</Page>
6tqwzwtp

6tqwzwtp1#

我猜你得到的错误,因为服务提供商,它不负责示例化ExploreCountiresPage。

ContentFrame.Navigate(typeof(ExploreCountriesPage));

上面的导航需要一个无参数的构造函数。
一种方法是使用类似this的代码,并在构造函数中获取ViewModel。

相关问题