【问题标题】:How do I switch views in child user controls in WPF?如何在 WPF 中的子用户控件中切换视图?
【发布时间】:2017-01-28 15:40:50
【问题描述】:

当视图由顶级 VM(如 MainWindowVM)管理时,我完全了解如何使用命令和数据模板在 WPF 中实现视图切换。我正在努力解决的问题是我有一个 MainWindow,它的 ContentControl 绑定到 CurrentView 属性,我想从 windows 内容控件内的视图和视图内的用户控件更新视图。在加载时,我将 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>

主菜单控制

<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>

【问题讨论】:

    标签: c# wpf xaml user-controls


    【解决方案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;
            }
        }
    }
    

    【讨论】:

    • 抱歉,我不明白,我的工作是自定义控件开发人员,所以我有时会遇到应用程序开发人员的问题
    • 在这里,我尝试在之前的回答中添加一些细节,希望对您有所帮助。
    • 非常感谢@Seb,非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2011-09-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多