当视图由顶级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>
答案 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;
}
}
}