如何在WPF中切换子用户控件中的视图?

时间:2017-01-28 15:40:51

标签: c# wpf xaml user-controls

当视图由顶级VM(如MainWindowVM)管理时,我完全理解如何使用命令和数据模板在WPF中实现视图切换。我正在努力的是我有一个MainWindow,它有一个ContentControl绑定到CurrentView属性,我想从Windows内容控件内的视图更新视图,用户控制insid视图。在加载时我将CurrentView设置为我的MainMenuVm实例,给我两个按钮。我想要的是更新来自此UserControl的按钮命令的视图,但我无法弄清楚如何更新CurrentView属性,因为它位于MainWindowVm中,而UserControl的数据上下文是MainMenuVm,在DataTemplate中设置。

我尝试连接事件,并获取MainWindow的数据上下文,但我无法使其工作。我有一个可以用来实例化ICommand属性的relayCommand类,我只需要帮助将命令从userControl传递给MainWindow。

所有帮助表示赞赏,如果需要,我可以发布代码。

我试图提供一些我的代码示例来澄清:

ViewModelBase

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

MainWindowVm

public class MainWindowVm : ViewModelBase
{
    private ViewModelBase _currentView;

    public ViewModelBase CurrentView
    {
        get { return _currentView; }
        set
        {
            _currentView = value;
            NotifyPropertyChanged();
        }
    }

    public MainWindowVm()
    {
        CurrentView = new MainMenuVm();

    }

}

MainWindow xaml

 <Window.DataContext>
        <vm:MainWindowVm/>
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:MainMenuVm}">
            <uc:MainMenuUserControl/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:NewJobVm}">
            <uc:NewJobUserControl/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition/>
            <RowDefinition Height="60"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="60"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="60"/>
        </Grid.ColumnDefinitions>
        <ContentControl Style="{DynamicResource PanelInnerStyle}"
                        Grid.Row="1"
                        Grid.Column="1"
                        Content="{Binding CurrentView}"
                        HorizontalContentAlignment="Center"/>

    </Grid>
</Window>

MainMenuuserontrol

<UserControl x:Class="Invoice.UserControls.MainMenuUserControl"
             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" 
             xmlns:local="clr-namespace:Invoice.UserControls"
             xmlns:vm="clr-namespace:Invoice.ViewModels"
             mc:Ignorable="d" 
             HorizontalAlignment="Center">

    <StackPanel Orientation="Horizontal">
        <Button Width="120"
                Height="120"
                Margin="5"
                ToolTip="Add New Job">

            <Image Source="/Resources/Add_Green.png"
                   Height="32"
                   Width="32"/>

        </Button>

        <Button Width="120"
                Height="120"
                Margin="5"
                ToolTip="Load Jobs">
            <Image Source="/Resources/Folder.png"
                   Height="32"
                   Width="32"/>
        </Button>
    </StackPanel>
</UserControl>

1 个答案:

答案 0 :(得分:1)

一个简单的方法是让MainWindowVm为其嵌套的视图模型提供委托:

public enum MenuCommands
{
    NEXT_PAGE = 0,
    PREVIOUS_PAGE = 1
}

public class MainMenuVm : ViewModelBase
{
    public MainMenuVm ( Action<MenuCommands> menuCommand )
    {
        _menuCommands = menuCommand;
    }

    private Action<MenuCommands> _menuCommands;

    /// <summary>
    /// Command binded from MainMenuUserControl.xaml
    /// </summary>
    public ICommand NextPageCommand
    {
        get { return _nextPageCommand ?? ( _nextPageCommand = new DelegateCommand ( NextPage ) ); }
    }
    private ICommand _nextPageCommand;

    private void NextPage ( )
    {
        // lets ask our MainWindowVM to switch the view
        _menuCommands ( MenuCommands.NEXT_PAGE );
    }
}

public class MainWindowVm : ViewModelBase
{
    /* ... */

    public MainWindowVm ( )
    {
        CurrentView = new MainMenuVm ( Navigate );

    }

    private void Navigate ( MenuCommands command )
    {
        // Implement your view switching logic here, like:

        switch ( command )
        {
            case MenuCommands.NEXT_PAGE:

                // CurrentView = new SomeOtherViewModel ( );

                break;
            case MenuCommands.PREVIOUS_PAGE:

                // CurrentView = new SomeOtherViewModel ( );

                break;
            default:
                break;
        }
    }
}
相关问题