如何在WPF MVVM中从子视图中的按钮切换一个窗口中的视图?

时间:2014-01-02 21:10:12

标签: c# wpf xaml mvvm

我在WPF MVVM应用中切换视图时遇到问题。 单击主视图中定义的菜单项时,切换工作正常。 单击子视图中的按钮时,切换不能按预期工作。

如果我在子视图(按钮所在的位置)以及父视图中设置contentcontrol, 子视图与先前显示的视图混合显示,一个视图中的按钮和我要切换到的视图中的背景。 没有它,调试器会显示正在发生的事情,ViewModelBase类中的类似步骤与从上述菜单中选择但窗口中没有可视更改时发生的情况相似。

我在ViewmodelBase中有命令(所有视图模型都直接或通过mainviewmodel继承)从类绑定中调用,例如在上面的XAML中。 CurrentViewModel是ViewModelBase中的一个属性,用于确定显示哪个视图。在ViewModelBase的构造函数中,我设置了命令,例如:

CategoryVMCommand = new RelayCommand(() => ExecuteCategoryVMCommand());

(上面的RelayCommand来自MVVM轻量级框架, 虽然它不是解决方案使用该框架所必需的)

我找到了许多针对类似问题的教程和答案,但无法使其中任何一个工作。例如,我尝试使用IOC在以下链接中遇到类似问题,但没有成功: MVVM Main window control bind from child user control

以下是一些涉及的代码和我正在做的事情的描述:

主窗口:      

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

    <DockPanel Margin="0,0,0,50">
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_Open"  Command="{Binding CategoryVMCommand}"/>
                <MenuItem Header="_Close"/>
                <MenuItem Header="_Save"/>
            </MenuItem>
            <MenuItem Header="_New">
                <MenuItem Header="_Create" Command="{Binding MainControlVMCommand}"/>
            </MenuItem>
        </Menu>
        <StackPanel></StackPanel>
    </DockPanel>


</Grid>
</Window>

然后我选择菜单项New,将显示以下视图:

<UserControl x:Class="WpfApplication1.MainControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">

<Grid>
    <!--<ContentControl Content="{Binding CurrentViewModel, Mode=OneWay}" />-->

    <TextBlock HorizontalAlignment="Left" Margin="10,20,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="39" Width="144" FontSize="24"><Run Language="en-gb" Text="TITLE"/><LineBreak/><Run Language="en-gb"/></TextBlock>
    <Button Content="Open category" HorizontalAlignment="Left" Margin="10,136,0,0" VerticalAlignment="Top" Width="153" Height="63" Command="{Binding CategoryVMCommand}" />
    <Button Content="Create new category" HorizontalAlignment="Left" Margin="10,218,0,0" VerticalAlignment="Top" Width="153" Height="63"/>
    <ListBox HorizontalAlignment="Left" Height="145" Margin="293,136,0,0" VerticalAlignment="Top" Width="201" Background="#FFDDDDDD"/>
    <TextBlock HorizontalAlignment="Left" Margin="293,107,0,0" TextWrapping="Wrap" Text="Recently Used" VerticalAlignment="Top" FontSize="18"/>

</Grid>
</UserControl>
单击

按钮打开类别,并执行Currentviewmodel设置代码(取决于MainControl视图中的ContenControl是否被注释掉) 返回或分配),然后执行ExecuteCategoryCommand。然后,在ViewModelBase构造函数中使用预期命令的行执行 要么没有变化,要么是我原先提到的混合结果

ViewModelBase class:

namespace ViewModel
{
    public class ViewModelBase : INotifyPropertyChanged
    {

    public event PropertyChangedEventHandler PropertyChanged;

    private ViewModelBase _currentViewModel;


    public ICommand CategoryVMCommand { get; private set; }

    public ICommand MainControlVMCommand { get; private set; }

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

    public ViewModelBase()
    {
        MainControlVMCommand = new RelayCommand(() => ExecuteMainControlVMCommand());
        CategoryVMCommand = new RelayCommand(() => ExecuteCategoryVMCommand());
    }

    public ViewModelBase CurrentViewModel
    {
        get
        {
            return _currentViewModel;
        }
        set
        {
            if (_currentViewModel == value)
                return;
            _currentViewModel = value;
            NotifyPropertyChanged("CurrentViewModel");
        }
    }

    protected void ExecuteCategoryVMCommand()
    {
        CurrentViewModel = null;
        CurrentViewModel = new CategoryVM();
    }
    protected void ExecuteMainControlVMCommand()
    {
        CurrentViewModel = null;
        CurrentViewModel = new MainControlVM();
    }
}
}

所以我的问题是如何单击子视图中的按钮,从ViewModelBase发送命令,设置CurrentViewModel,并在一个窗口中成功切换视图,而不会显示先前显示的视图的剩余部分?

感谢您的帮助。

0 个答案:

没有答案