使用 mvvmcross 和命令在通用应用程序中使用 rss 提要的不同部分

Using different parts of rss feed in a universal app using mvvmcross and commands

所以我一直在尝试使用通用应用程序和 mvvmcross 为 win10 构建一个简单的 rss 提要应用程序,它将执行以下操作:

我遇到的问题是将相同 RssItems 的不同部分绑定到不同的控件,但保持它们之间的关系。我对这两种技术都不熟悉,但我认为这应该是可行的,我只是找不到方法。

这些是我写的代码的相关部分:

viewModel.cs:

class FirstViewModel : MvxViewModel
{
    private List<string> _rssItems;

    public List<string> RssItems
    {
        get { return _rssItems; }
        set { _rssItems = value; RaisePropertyChanged(() => RssItems); }
    }

    public MvxCommand SelectionChangedCommand
    {
        get
        {
            return new MvxCommand(() =>
            {
                LoadRssItems();
            });
        }
    }

    private async void LoadRssItems()
    {
        List<string> feedItems = new List<string>();
        SyndicationClient rssReaderClient = new SyndicationClient();
        SyndicationFeed rssFeed = await rssReaderClient.RetrieveFeedAsync(new Uri("xml address"));

        if (rssFeed != null)
        {
            foreach (var item in rssFeed.Items)
            {
                feedItems.Add(item.Title.Text);
                RssItemsOrinigal.Add(item);
            }

            RssItems = feedItems;
        }
    }

和firstView.xaml:

<views:MvxWindowsPage
    x:Class="RssReader.Views.FirstView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:RssReader.Views"
    xmlns:views="using:MvvmCross.WindowsUWP.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <RelativePanel>
            <Button x:Name="HamburgerButton"
                    RelativePanel.AlignLeftWithPanel="True"
                    FontFamily="Segoe MDL2 Assets"
                    FontSize="36"
                    Content="&#xE700;"
                    Click="HamburgerButton_Click"/>

        <SplitView Grid.Row="1"
                   x:Name="sv"
                   DisplayMode="CompactOverlay"
                   OpenPaneLength="200"
                   CompactPaneLength="50">

            <SplitView.Pane>
                <ListBox x:Name="lstMenuItems" SelectionMode="Single">
                    <ListBoxItem x:Name="ListBoxItem1">
                        <StackPanel Orientation="Horizontal">
                            <Button FontFamily="Segoe MDL2 Assets" FontSize="36" Command="{Binding SelectionChangedCommand}">&#xE14A;</Button>
                            <TextBlock FontSize="24" Text="Website 1" />
                        </StackPanel>
                    </ListBoxItem>                    
                </ListBox>
            </SplitView.Pane>
            <SplitView.Content>
                <ListBox ItemsSource="{Binding RssItems}"/>
            </SplitView.Content>
        </SplitView>

    </Grid>
</views:MvxWindowsPage>

一种方法是将 ContentPresenterListBox 一起使用,并在每次 select 一个项目或想回到 ListBox:

<Page.Resources>
    <DataTemplate x:Key="DetailContent">
        <WebView Source="{Binding DetailUri}" />
    </DataTemplate>
    <DataTemplate x:Key="ListBoxContent">
        <TextBlock Text="{Binding Title}" />
    </DataTemplate>
</Page.Resources>

...
<SplitView.Content>
    <Grid>
        <ContentPresenter Content="{x:Bind listBox.SelectedItem, Mode=OneWay}"
                          ContentTemplate="{StaticResource DetailContent}" Visibility="{x:Bind VM.IsVisible, Mode=OneWay}" />
        <ListBox x:Name="listBox" ItemsSource="{x:Bind VM.RssItems}"
                 ItemTemplate="{StaticResource ListBoxContent}" SelectionChanged="{x:Bind VM.listBox_SelectionChanged}" />
        <Button Content="Close and Show ListBox" VerticalAlignment="Bottom" Visibility="{x:Bind VM.IsVisible, Mode=OneWay}"
                Click="{x:Bind VM.IsVisible_Clicked}" />
    </Grid>
</SplitView.Content>

例如在这个页面的ViewModel中:

public class Page6ViewModel : INotifyPropertyChanged
{
    public ObservableCollection<ListBoxDetail> RssItems;

    private Visibility _IsVisible = Visibility.Collapsed;

    public Visibility IsVisible
    {
        get { return _IsVisible; }
        set
        {
            if (value != _IsVisible)
            {
                _IsVisible = value;
                OnpropertyChanged();
            }
        }
    }

    public Page6ViewModel()
    {
        RssItems = new ObservableCollection<ListBoxDetail>();
        RssItems.Add(new ListBoxDetail { Title = "Item 1", DetailUri = "" });
        RssItems.Add(new ListBoxDetail { Title = "Item 2", DetailUri = "https://msdn.microsoft.com/en-us/library/windows/apps/ms668604(v=vs.105).aspx" });
        RssItems.Add(new ListBoxDetail { Title = "Item 3", DetailUri = "https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemscontrol.itemssource.aspx" });
    }

    private ListBox listBox;

    public void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        listBox = sender as ListBox;
        listBox.Visibility = Visibility.Collapsed;
        IsVisible = Visibility.Visible;
    }

    public void IsVisible_Clicked(object sender, RoutedEventArgs e)
    {
        listBox.Visibility = Visibility.Visible;
        IsVisible = Visibility.Collapsed;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnpropertyChanged([CallerMemberName]string propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

另一种常见的方法是将Frame用作SpiltViewContent,然后首先为ListBox创建一个页面,为WebView创建一个页面将此框架导航到 ListBox 的页面,在 SelectionChanged 事件中,您可以将 uri 作为参数发送并将此框架导航到 WebView 的页面。这个方法网上有很多例子,大家可以搜索一下。