1

通过创建具有水平导航项目类型、MVVM Light设计模式和两个空白页面(MainPage 和 StatsPage)的 Windows Template Studio 应用程序开始学习 UWP 开发。

在 MainPage 我有一个项目列表,我想在用户点击相关时在 StatsPage 中显示所选项目的统计信息NavigationViewItem。在我的 wpf 应用程序中,我会在主视图中的按钮上设置一个RelayCommandwith 命令参数,然后在视图模型中,使用参数/参数调用命令的方法以使用正确的信息打开 Stats 视图。在创建的 Template Studio 应用程序NavigationViewItem中,ShellPage 调用OnItemInvoked()其 VM 中的 VM,该 VM 不知道 MainPage 视图中的选择。

<winui:NavigationView.MenuItems>
  <winui:NavigationViewItem x:Uid="Shell_Main" helpers:NavHelper.NavigateTo="LG_Ess.ViewModels.MainViewModel" />
  <winui:NavigationViewItem x:Uid="Shell_Stats" helpers:NavHelper.NavigateTo="LG_Ess.ViewModels.StatsViewModel" />
</winui:NavigationView.MenuItems>
  <i:Interaction.Behaviors>
    <ic:EventTriggerBehavior EventName="ItemInvoked">
      <ic:InvokeCommandAction Command="{x:Bind ViewModel.ItemInvokedCommand}" />
    </ic:EventTriggerBehavior>
  </i:Interaction.Behaviors>

如何通过 ShellPage 将 MainPage 选定项作为参数传递给 StatsPage NavigationViewItem?我可以通过在我的 MainPage 中添加一个按钮并隐藏 Shell 导航来解决它,但我更喜欢在 Template Studio 样式中完成它。

进一步调查表明,ShellViewModel 似乎是 Template Studio 创建的所有页面的默认 DataContext。在我的页面中,我通过添加以下内容将数据上下文设置为自动生成的视图模型:

<Page.DataContext>
  <local:{PageName}ViewModel/>
</Page.DataContext>

因此,似乎我可以拥有一个 ViewModel 并将页面视为 UserControls,或者将每个页面的 DataContext 映射到它自己的 ViewModel,然后做一些 ViewModelLocator 跳舞以访问另一个 VM 中的属性。

4

1 回答 1

0

因此,似乎我可以拥有一个 ViewModel 并将页面视为 UserControls,或者将每个页面的 DataContext 映射到它自己的 ViewModel,并做一些 ViewModelLocator 跳舞以访问另一个 VM 中的属性。

正确的。您可以在 MainViewModel 中定义一个“SelectedStats”相关属性,并使 ListView 的 SelectedItem 绑定到该属性并设置Mode=TwoWay。然后,在您的“StatsPage”上,您可以使用EventTriggerBehavior在 StatsViewModel 中绑定“LoadedCommand”,如“ShellPage”。在 StatsViewModel 中,您可以通过调用ViewModelLocator.Current.MainViewModel.SelectedStats.

请参阅我的简单代码示例:

<!--MainPage.xaml-->
<ListView ItemsSource="{x:Bind ViewModel.list}" SelectedItem="{x:Bind ViewModel.SelectedStats,Mode=TwoWay}">
</ListView>
public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        list = new ObservableCollection<string>();
        list.Add("string1");
        list.Add("string2");
        list.Add("string3");
    }

    public ObservableCollection<string> list { get; set; }

    private object _SelectedStats;

    public object SelectedStats
    {
        get { return _SelectedStats; }
        set
        {
            if (_SelectedStats != value)
            {
                _SelectedStats = value;
                RaisePropertyChanged("SelectedStats");
            }
        }
    }
}
<!--StatsPage.xaml-->
<i:Interaction.Behaviors>
    <ic:EventTriggerBehavior EventName="Loaded">
        <ic:InvokeCommandAction Command="{x:Bind ViewModel.LoadedCommand}" />
    </ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
public class StatsViewModel : ViewModelBase
{
    public StatsViewModel()
    {
    }

    private ICommand _LoadedCommand;
    public ICommand LoadedCommand => _LoadedCommand ?? (_LoadedCommand = new RelayCommand(LoaedAsync));

    private async void LoaedAsync()
    {
        var selectedObject = ViewModelLocator.Current.MainViewModel.SelectedStats;
        //TODO:...
        await Task.CompletedTask;
    }
}
于 2019-06-27T02:45:03.620 回答