WPF MVVM如何设置contentcontrol的初始值

时间:2018-04-19 08:00:15

标签: wpf mvvm

我在我的应用程序中实现了类似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中声明它会更好。这可能吗?

2 个答案:

答案 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>();
}