我在我的应用程序中实现了类似this的内容。在我的xaml中我有这个:
Window.Resources>
<DataTemplate x:Shared="False" DataType="{x:Type local:View1ViewModel}">
<local:View1/>
</DataTemplate>
<DataTemplate x:Shared="False" DataType="{x:Type local:View2ViewModel}">
<local:View2/>
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentView}" />
这可行,我可以通过在VM中设置“CurrentView”属性来在视图之间切换。但我想知道如何设置初始值(在用户交互之前)?目前我在我的VM中有这个:
CurrentView = new View1();
但是MVVM之后呢?这似乎是错误的,因为我正在从我的ViewModel引用/实例化一个View。如果可以在xaml中声明它会更好。这可能吗?
答案 0 :(得分:1)
您可以使用 Conductor 类中的 ActivateItem 方法,
首先让 ShellViewModel 从 Conductor
继承public class ShellViewModel :Conductor<object>
然后在承包商中
public ShellViewModel()
{
ActivateItem(new HomePageChildViewModel());
}
HomePageChildViewModel 是您要显示的内容。
答案 1 :(得分:0)
正如评论中所提到的,如果你想先做viewmodel,那么CurrentView应该是CurrentViewModel。否则这些模板有点没用 这是我不久前放在一起的东西。 主窗口:
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:LoginViewModel}">
<local:LoginUC/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:UserViewModel}">
<local:UserUC/>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="Login Page"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:LoginViewModel}"
/>
<Button Content="User Page"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:UserViewModel}"
/>
</StackPanel>
<ContentControl Grid.Column="1"
Content="{Binding CurrentViewModel}"
/>
</Grid>
请注意,我有一个命令,它将Type作为参数 这两种类型的模板可以为您提供视图 哦....我打电话给我的属性CurrentViewModel。因为它将向我的contentcontrol的内容呈现其中一个视图模型的实例。
视图模型:
public class MainWindowViewModel : INotifyPropertyChanged
{
private object currentViewModel;
public object CurrentViewModel
{
get { return currentViewModel; }
set { currentViewModel = value; RaisePropertyChanged(); }
}
private RelayCommand<Type> navigateCommand;
public RelayCommand<Type> NavigateCommand
{
get
{
return navigateCommand
?? (navigateCommand = new RelayCommand<Type>(
vmType =>
{
CurrentViewModel = null;
CurrentViewModel = Activator.CreateInstance(vmType);
}));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
首先将属性设置为null可以保证您不会在视图中保留任何状态。我获取从命令传入的类型并创建该viewmodel的实例。然后通过适当的数据模板进行模板化。这只是一个特别简单的说明性示例,一个明显的改进是使用键入类型的字典保留每个视图模型的状态。因此,您只需在会话中实例化一次给定的viewmodel类型。
首先是viewmodel。
有些人更喜欢先观看。当然,如果你每次都想要一个新窗口,那么可能就是你想要进入的方向。先查看可以说是一个视图责任,你可以处理在视图中实例化一个新视图。如果你想。这可以使用路由事件和参数来完成。
看起来像是:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox HorizontalContentAlignment="Stretch"
Button.Click="Button_Click"
>
<Button Content="Home" Tag="{x:Type local:HomeView}"/>
<Button Content="Departments" Tag="{x:Type local:DepartmentView}"/>
</ListBox>
<ContentControl Name="NavigationParent"
Grid.Column="1"/>
</Grid>
此版本保留每个视图的状态。该视图将在此模式中实例化它自己的viewmodel。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Navigate(typeof(HomeView));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = (Button)e.OriginalSource;
Navigate(btn.Tag as Type);
}
private void Navigate (Type viewType)
{
UserControl uc;
if (Views.ContainsKey(viewType))
{
uc = Views[viewType];
}
else
{
uc = (UserControl)Activator.CreateInstance(viewType);
Views[viewType] = uc;
}
NavigationParent.Content = uc;
}
private Dictionary<Type, UserControl> Views = new Dictionary<Type, UserControl>();
}