从另一个视图更改ContentControl内容

时间:2014-08-07 15:42:45

标签: c# wpf mvvm mvvm-light

我有问题如何控制内容控件中的视图。我有两个视图,其中有按钮,我想在其中一个按钮中点击将发生视图更改为第二个。我正在使用MVVM,我的问题是我不知道如何将ViewModel绑定到ContentControl。也许我的代码告诉你的不仅仅是我可以澄清:

// Main window view
<Window x:Class="ContentControlTestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding Main, Source={StaticResource Locator}}">
    <Grid>
        <ContentControl Content="{Binding CurrentViewModel}"/>
    </Grid>
</Window>
// Main window view model
public class MainViewModel : ViewModelBase
{
    private ViewModelBase _currentViewModel;

    public ViewModelBase CurrentViewModel
    {
        get { return _currentViewModel; }
        set
        {
            _currentViewModel = value; 
            RaisePropertyChanged("CurrentViewModel");
        }
    }
    private ViewModelLocator Locator
    {
        get
        {
            return App.Current.Resources["Locator"] as ViewModelLocator;
        }
    }

    public MainViewModel()
    {
        CurrentViewModel = Locator.FirstControl;
    }
}

//App.xaml
<Application x:Class="ContentControlTestApp.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:ContentControlTestApp.ViewModel" xmlns:view="clr-namespace:ContentControlTestApp.View">
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
  <DataTemplate DataType="{x:Type vm:FirstControlViewModel}">
      <view:FirstControlView></view:FirstControlView>
  </DataTemplate>
    <DataTemplate DataType="{x:Type vm:SecondControlViewModel}">
        <view:SecondControlView></view:SecondControlView>
    </DataTemplate>
</Application.Resources>
</Application>

//First Control View
<UserControl x:Class="ContentControlTestApp.View.FirstControlView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <StackPanel>
        <Label Content="First Control" />
        <Button Content="Switch to second control" Command="{Binding SwitchToSecondControlCommand}"/>
    </StackPanel>
</Grid>
</UserControl>

//First Control view model
public class FirstControlViewModel:ViewModelBase
{
    private RelayCommand _switchToSecondControlCommand;

    public ICommand SwitchToSecondControlCommand
    {
        get
        {
            return _switchToSecondControlCommand ??
                   (_switchToSecondControlCommand = new RelayCommand(SwitchToSecondControlExecute));
        }
    }

    private void SwitchToSecondControlExecute()
    {
        //I don't know what to do here
    }
}

//Second Control View
<UserControl x:Class="ContentControlTestApp.View.SecondControlView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <StackPanel>
        <Label Content="Second Control" />
        <Button Content="Switch to first control" Command="{Binding SwitchToFirstControlCommand}"/>
    </StackPanel>
</Grid>
</UserControl>

//Second Control view model
public class SecondControlViewModel:ViewModelBase
{
    private RelayCommand _switchToFirstControlCommand;

    public ICommand SwitchToFirstControlCommand
    {
        get
        {
            return _switchToFirstControlCommand ??
                   (_switchToFirstControlCommand = new RelayCommand(SwitchToSecondControlExecute));
        }
    }

    private void SwitchToSecondControlExecute()
    {
        //I don't know what to do here
    } 
}

//ViewModelLocator
public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<MainViewModel>();
        SimpleIoc.Default.Register<FirstControlViewModel>();
        SimpleIoc.Default.Register<SecondControlViewModel>();
    }

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

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

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

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

我不知道如何在MainViewModel中更改CurrentViewModel,例如FirstControlViewModel的命令。任何的想法?我想过一些事情,但这看起来并不好。有没有人有任何想法?

由于

1 个答案:

答案 0 :(得分:1)

首先要改变视图,我们更改视图模型(假设您已正确声明了DataTemplate):

<ContentControl Content="{Binding CurrentViewModel}"/>

...

CurrentViewModel = new OtherViewModel();

显然,您只能通过MainViewModel执行此操作。因此,您应该处理Button ICommand 中的MainViewModel ,然后将SwitchToFirstControlCommand移到那里并将Button.Command Binding Path更改为:

<Button Content="Switch to first control" Command="{Binding DataContext.
    SwitchToFirstControlCommand, RelativeSource={RelativeSource 
    AncestorType={x:Type MainWindow}}}" />

现在在您的主视图模型中:

private void SwitchToSecondControlExecute()
{
    CurrentViewModel = new OtherViewModel();
}