为了导航并将参数传递给相应的页面视图模型,我坚持您的模式并使用了组合。我介绍了一个组合容器,它将所有页面视图模型保存在 Dictionary<string, IPageViewModel> 中。因此所有的页面视图模型都必须实现这个接口。作为键,我使用了页面视图模型的类型名称(例如nameof(FirstViewModel))。我还引入了一个名为PageNavigationParameter 的新属性,它绑定到TextBox 以获取内容(应该传递给相应的页面视图模型)。
第二个Dictionary<string, string> 将每个页面视图模型的显示名称(将在ComboBox 中显示的页面名称)映射到实际的页面视图模型名称(与类名称匹配,例如nameof(FistViewModel))。这样,您可以通过类名或在导航范围内从页面显示名称获取所需的页面视图模型。
要从ComboBox 中选择页面,您可以这样做:
- 在视图模型中创建页面名称集合并将其绑定到
ComboBox.ItemSource
- 将
ComboBox.SelectedItem 属性绑定到视图模型
- 当视图模型的属性改变时导航到页面
要使这个示例工作,您需要一个所有页面视图模型都必须实现的通用接口(例如class FirstViewModel : IPageViewModel)。此接口必须至少包含PageNavigationParameter
页面视图模型界面
interface IPageViewModel
{
string PageNavigationParameter { get; set; }
}
主视图模型(使用合成)
class MainViewModel
{
public MainViewModel()
{
// The Dictionary to get the page view model name
// that maps to a page display name
this.PageViewModelNameMap = new Dictionary<string, string>()
{
{"First Page", nameof(FirstViewModel)},
{"Second Page", nameof(SecondViewModel)}
};
// The ComboBox's items source
// that holds the page view model display names
this.PageNames = new ObservableCollection<string>(this.PageViewModelNameMap.Keys);
// The Dictionary that stores all page view models
// that can be retrieved by the page view model type name
this.PageViewModels = new Dictionary<string, IPageViewModel>()
{
{nameof(FirstViewModel), new FirstViewModel()},
{nameof(SecondViewModel), new SecondViewModel()}
};
this.CurrentPageViewModel = this.PageViewModels[nameof(FirstViewModel)];
this.PageNavigationParameter = string.Empty;
}
// You can use this method as execute handler
// for your NavigateToPage command too
private void NavigateToPage(object parameter)
{
if (!(parameter is string pageName))
{
return;
}
if (this.PageViewModelNameMap.TryGetValue(pageName, out string pageViewModelName)
{
if (this.PageViewModels.TryGetValue(pageViewModelName, out IPageViewModel pageViewModel)
{
pageViewModel.PageNavigationParameter = this.PageNavigationParameter;
this CurrentPageViewModel = pageViewModel;
}
}
}
private bool CanExecuteNavigation(object parameter) => parameter is string destinationPageName && this.PageViewModelNameMap.Contains(destinationPageName);
private void OnSelectedPageChanged(string selectedPageName)
{
NavigateToPage(selectedPageName);
}
private ObservableCollection<string> pageNames;
public ObservableCollection<string> PageNames
{
get => this.pageNames;
set
{
this.pageNames = value;
OnPropertyChanged();
}
}
private string selectedPageName;
public string SelectedPageName
{
get => this.selectedPageName;
set
{
this.selectedPageName = value;
OnPropertyChanged();
OnSelectedPageChanged(value);
}
}
private string pageNavigationParameter;
public string PageNavigationParameter
{
get => this.pageNavigationParameter;
set
{
this.pageNavigationParameter= value;
OnPropertyChanged();
}
}
private Dictionary<string, ViewModelBase> pageViewModels;
public Dictionary<string, ViewModelBase> PageViewModels
{
get => this.pageViewModels;
set
{
this.pageViewModels = value;
OnPropertyChanged();
}
}
private Dictionary<string, string> pageViewModelNameMap;
public Dictionary<string, string> PageViewModelNameMap
{
get => this.pageViewModelNameMap;
set
{
this.pageViewModelNameMap = value;
OnPropertyChanged();
}
}
private IPageViewModel currentPageViewModel;
public IPageViewModel CurrentPageViewModel
{
get => this.currentPageViewModel;
set
{
this.currentPageViewModel= value;
OnPropertyChanged();
}
}
}
具有跨页面范围的控件必须将MainViewModel 作为其DataContext。
XAML sn-p
<!-- The page menu (DataContext is MainViewModel) -->
<ComboBox SelectedItem="{Binding SelectedPageName}" ItemsSource="{Binding PageNames}" />
<!-- The navigation parameter TextBox (DataContext is MainViewModel) -->
<TextBox Text="{Binding PageNavigationParameter}" />
对于您的导航按钮命令,您可以使用相同的 MainViewModel.NavigateToPage() 方法作为执行委托处理程序和 CanExecuteNavigation 作为可以执行处理程序。所以你现在有一个导航命令(例如NavigateToPage),它通过将页面显示名称传递为CommandParameter来导航到目标页面。