根据子视图模型更改wpf单页面应用程序中的视图

时间:2015-12-16 08:45:39

标签: c# wpf mvvm

我在wpf中编写应用程序并使用mvvm模式。 我尝试使用ContentControl和DataTemplate实现单页面应用程序。 在我的应用程序中,我想根据子视图模型切换视图,如下所示: 我有一个主窗口,其内容控件的内容绑定到MainViewModel中的属性:

public BaseViewModel CurrentViewModel { get; set; }

在我写的consturctor中:

CurrentViewModel = new LoginViewModel();
在LoginViewModel中的

我有一个获取名称和密码的函数,并检查细节是否正确。 如果没问题,我想将MainViewModel中的CurrentViewModel设置为NavigationViewModel。

但是当我查找示例时,我发现只能在主视图模型中直接切换viewmodel。 我该怎么办?

3 个答案:

答案 0 :(得分:4)

如果我正确理解了您的问题,那么您是在询问登录完成后如何从service did not shut down properly after receiving a preshutdown control内更改CurrentViewModel

你不应该这样做。 LoginViewModel应该担心登录,并且不应该知道它的使用位置或应用程序的任何其他部分。

LoginViewModel是拥有子VM并且编排应用程序流的人,因此MainViewModel应该进行切换。

由于您希望在登录完成后切换视图,所以您需要MainViewModel告诉您登录已完成确定。这样做的两个显而易见的方法是:

  1. LoginViewModel公开了LoginViewModel订阅的LoginComplete个事件,或
  2. MainViewModelMainViewModel构造函数提供LoginComplete ActionLoginViewModel在登录完成后调用。
  3. LoginViewModel

答案 1 :(得分:2)

使用MvvmLight框架可以构建这样的怪物。

MainWindow.xaml

  

DataContext =“{Binding Source = {StaticResource Locator},Path = Main}”

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Content="BaseView" Height="25" Width="80" Command="{Binding SwitchToBaseCommand}"/>
        <Button Grid.Row="1" Content="NavigationView" Height="25" Width="100" Command="{Binding SwitchToNavigationCommand}"/>
    </Grid>
    <ContentControl Grid.Column="1" Content="{Binding CurrentViewModel}"/>
</Grid>

BaseView.xaml

  

DataContext =“{Binding Source = {StaticResource Locator},Path = BaseViewModel}”

<Grid>
    <Label Content="{Binding Message}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

NavigationView.xaml

  

DataContext =“{Binding Source = {StaticResource Locator},Path = NavigationViewModel}”

<Grid>
    <Label Content="{Binding Message}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

的App.xaml

  

xmlns:Views =“clr-namespace:WpfApplication.Views”xmlns:ViewModels =“clr-namespace:WpfApplication.ViewModel”

  <Application.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:WpfApplication233.ViewModel" />

        <DataTemplate DataType="{x:Type ViewModels:BaseViewModel}">
            <Views:BaseView/>
        </DataTemplate>

        <DataTemplate DataType="{x:Type ViewModels:NavigationViewModel}">
            <Views:NavigationView/>
        </DataTemplate>

    </ResourceDictionary>
</Application.Resources>

ViewModelLocator.cs

public class ViewModelLocator
{
    /// <summary>
    /// Initializes a new instance of the ViewModelLocator class.
    /// </summary>
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        SimpleIoc.Default.Register<MainViewModel>();
        SimpleIoc.Default.Register<BaseViewModel>();
        SimpleIoc.Default.Register<NavigationViewModel>();
    }

    public MainViewModel Main
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }

    public BaseViewModel BaseViewModel
    {
        get
        {
            return ServiceLocator.Current.GetInstance<BaseViewModel>();
        }
    }

    public NavigationViewModel NavigationViewModel
    {
        get
        {
            return ServiceLocator.Current.GetInstance<NavigationViewModel>();
        }
    }

    public static void Cleanup()
    {
        // TODO Clear the ViewModels
    }
}

MainViewModel.cs

public class MainViewModel : ViewModelBase
{
    private ViewModelBase currentViewModel;
    public ViewModelBase CurrentViewModel
    {
        get
        {
            return this.currentViewModel;
        }

        set
        {
            this.currentViewModel = value;
            this.RaisePropertyChanged("CurrentViewModel");
        }
    }
    public RelayCommand SwitchToBaseCommand
    {
        get
        {
            return new RelayCommand(() => SwitchToBase());
        }
    }

    public RelayCommand SwitchToNavigationCommand
    {
        get
        {
            return new RelayCommand(() => SwitchToNavigation());
        }
    }

    public void SwitchToBase()
    {
        CurrentViewModel = ServiceLocator.Current.GetInstance<BaseViewModel>();
    }

    public void SwitchToNavigation()
    {
        CurrentViewModel = ServiceLocator.Current.GetInstance<NavigationViewModel>();
    }

}

BaseViewModel.cs

public class BaseViewModel :ViewModelBase
{
    public string Message {get; set;}
    public BaseViewModel()
    {
        Message = "Message from BaseViewModel View Model";
    }
}

NavigationViewModel.cs

    public class NavigationViewModel:ViewModelBase
{
    public string Message { get; set; }
    public NavigationViewModel()
    {
        Message = "Message from Navigation View Model";
    }
}

答案 2 :(得分:0)

如果您想根据DataTemplates动态切换Views,则可以使用ViewModel

<Window>
   <Window.Resources>
      <DataTemplate DataType="{x:Type ViewModelA}">
         <localControls:ViewAUserControl/>
      </DataTemplate>
      <DataTemplate DataType="{x:Type ViewModelB}">
         <localControls:ViewBUserControl/>
      </DataTemplate>
   <Window.Resources>
  <ContentPresenter Content="{Binding CurrentView}"/>
</Window>

如果Window.DataContextViewModelA的实例,则会显示ViewAWindow.DataContextViewModelB的实例,然后是ViewB将会显示。

我见过并阅读过的最好的例子是Rachel LimSee the example.