我想制作一个带有 ListBox 导航的 UWP 应用程序,其所选项目确定框架的内容。When the selection changes, the frame content should change. 我找到了一个示例(下面的方法 1),但它在后面的代码中使用了事件处理程序。我想通过这个项目学习 MVVM,因此想使用 MVVM 解决这个问题。我是 MVVM 的新手,我目前的理解是,为了将 View 与 ViewModel 分离,ViewModel 不应引用任何特定于 View 的内容。这是一个正确的理解吗?我能想到的使用 ViewModel 更改框架视图的唯一方法是基本上将事件处理程序代码移动到 ViewModel 并将 Frame 传递给构造函数(下面的方法 2)。但这违反了我对 ViewModel 与 View 关系的理解,因为 ViewModel 引用了 View 中事物的特定实例;此外,这似乎是毫无意义的开销,而且它会给组织带来很少的好处。
您将如何针对此问题实施 MVVM 解决方案?或者这是使用事件处理程序更好的情况?
方法 1 - 事件处理程序: 此代码基于 Microsoft 提供的示例。(这里是相关代码的链接:https ://github.com/microsoft/Windows-universal-samples/tree/master/Samples/Playlists/cs )
public sealed partial class MainPage : Page
{
List<Scenario> scenarios = new List<Scenario>
{
new Scenario() { Title = "Scenario 1", ClassType = typeof(Scenario1) },
new Scenario() { Title = "Scenario 2", ClassType = typeof(Scenario2) }
};
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ScenarioControl.ItemsSource = scenarios;
}
private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox scenarioListBox = sender as ListBox;
Scenario s = scenarioListBox.SelectedItem as Scenario;
if (s != null)
{
ScenarioFrame.Navigate(s.ClassType);
}
}
}
public class Scenario
{
public string Title { get; set; }
public Type ClassType { get; set; }
public override string ToString()
{
return Title;
}
}
<!-- MainPage.xaml -->
<Grid>
<SplitView x:Name="Splitter" IsPaneOpen="True" DisplayMode="Inline">
<SplitView.Pane>
<RelativePanel>
<ListBox x:Name="ScenarioControl" SelectionChanged="ScenarioControl_SelectionChanged"/>
</RelativePanel>
</SplitView.Pane>
<RelativePanel>
<Frame x:Name="ScenarioFrame" />
</RelativePanel>
</SplitView>
</Grid>
方法 2 - MVVM(?):
<!-- MainPage.xaml -->
<Grid>
...
<ListBox x:Name="ScenarioControl" SelectionChanged="{x:Bind MyViewModel.SwitchScenario}"/>
...
</Grid>
// MainPage.xaml.cs
...
public MainPage()
{
this.InitializeComponent();
MyViewModel = new MyViewModel(ScenarioFrame);
}
...
MyViewModel MyViewModel { get; set; }
}
// MyViewModel.cs
public class MyViewModel
{
public MyViewModel(Frame scenarioFrame)
{
ScenarioFrame = scenarioFrame;
}
public void SwitchScenario(object sender, SelectionChangedEventArgs e)
{
ListBox scenarioListBox = sender as ListBox;
Scenario s = scenarioListBox.SelectedItem as Scenario;
if (s != null)
{
ScenarioFrame.Navigate(s.ClassType);
}
}
public Frame ScenarioFrame { get; set; }
}