[英]How do I switch views in child user controls in WPF?
I fully understand how to implement view switch in WPF using commands and data templates when the view is managed by a top level VM, like a MainWindowVM. 我完全了解当视图由顶级VM(例如MainWindowVM)管理时,如何使用命令和数据模板在WPF中实现视图切换。 What I am struggling with is where I have a MainWindow which has a ContentControl bound to a CurrentView property and I want to update the view from views inside the windows content control, and user controls insid ethe views. 我正在苦苦挣扎的地方是一个MainWindow,它的ContentControl绑定到CurrentView属性,我想从Windows内容控件内部的视图更新视图,而用户控件则包含这些视图。 On loadup I set the CurrentView to an instance of my MainMenuVm, giving me two buttons. 在加载时,我将CurrentView设置为MainMenuVm的一个实例,给了我两个按钮。 What I want is to update the view on a button command from this UserControl, but I can't figure out how to update the CurrentView property as it resides in MainWindowVm, and the UserControl's data context is to MainMenuVm, as set in the DataTemplate. 我想要的是从此UserControl更新按钮命令上的视图,但是我不知道如何更新CurrentView属性,因为它位于MainWindowVm中,而UserControl的数据上下文是MainMenuVm,如在DataTemplate中设置的那样。
I have tried hooking up events, and getting the data context of the MainWindow but I can't get it to work. 我尝试挂钩事件,并获取MainWindow的数据上下文,但无法正常工作。 I have a relayCommand class that I can use to instantiate ICommand properties, I just need help with passing the commands from the userControl to the MainWindow. 我有一个用来实例化ICommand属性的relayCommand类,我只需要帮助将命令从userControl传递到MainWindow。
All help appreciated, I can post code if needed. 感谢所有帮助,如果需要,我可以发布代码。
I have tried to provide some examples of my code to clarify: 我试图提供一些示例代码来阐明:
ViewModelBase ViewModelBase
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindowVm 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 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 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>
A simple way to do it would be for the MainWindowVm to give a delegate to its nested viewmodels: 一种简单的方法是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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.