我有一个CateringMenuView,我通过点击一个菜单在UserControls之间导航,它工作正常。
我使用以下模式:
https://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/
在其中一个usercontrol(NewRegularOrderView)中有一个按钮。通过单击此按钮,我想导航到另一个usercontrol。为了做到这一点,我使用了我在这里的答案:
Navigate between UserControls with Event Aggegator
但是当我点击按钮时没有任何反应。
你能帮忙找到原因吗?
<UserControl.Resources>
<DataTemplate DataType="{x:Type cvm:NewDeliveryComOrderViewModel}">
<cv:NewDeliveryComOrderView/>
</DataTemplate>
<DataTemplate DataType="{x:Type cvm:NewRegularOrderViewModel}">
<cv:NewRegularOrderView/>
</DataTemplate>
<DataTemplate DataType="{x:Type cvm:FillOrderViewModel}">
<cv:FillOrderView/>
</DataTemplate>
<cvm:CateringMenuViewModel x:Key="menu"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource menu}}">
<StackPanel>
<Menu>
<MenuItem Header="New Order">
<ItemsControl ItemsSource="{Binding PageViewModels}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay, Source={StaticResource menu}}" CommandParameter="{Binding}" TextDecorations="{x:Null}">
<InlineUIContainer>
<TextBlock Text="{Binding Name}"/>
</InlineUIContainer>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</MenuItem>
</Menu>
</StackPanel>
<Border Grid.Row="1" BorderThickness="1" CornerRadius="8" >
<ContentControl Content="{Binding CurrentUserControl}" Margin="0,0,-1,0"/>
</Border>
</Grid>
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
PageViewModels.Add(new NewRegularOrderViewModel());
PageViewModels.Add(new NewDeliveryComOrderViewModel());
PageViewModels.Add(new FillOrderViewModel());
// Set starting page
CurrentUserControl = PageViewModels[0];
}
#region Fields
private List<IUserContentViewModel> _pageViewModels;
public List<IUserContentViewModel> PageViewModels
{
get
{
if (_pageViewModels == null)
_pageViewModels = new List<IUserContentViewModel>();
return _pageViewModels;
}
}
private IUserContentViewModel _currentUserControl;
public IUserContentViewModel CurrentUserControl
{
get { return _currentUserControl; }
set
{
if (value != _currentUserControl)
{
_currentUserControl = value;
OnPropertyChanged("CurrentUserControl");
}
}
}
#region Methods
private void ChangeViewModel(IUserContentViewModel viewModel)
{
if (!PageViewModels.Contains(viewModel))
PageViewModels.Add(viewModel);
CurrentUserControl = PageViewModels
.FirstOrDefault(vm => vm == viewModel);
}
#endregion
private ICommand _changePageCommand;
#endregion
public ICommand ChangePageCommand
{
get
{
if (_changePageCommand == null)
{
_changePageCommand = new RelayCommand(
p => ChangeViewModel((IUserContentViewModel)p),
p => p is IUserContentViewModel);
}
return _changePageCommand;
}
}
}
现在,当我在NewRegularOrderView上时,我想点击一个按钮导航到FillOrderView。
在ChangeViewModel(IUserContentViewModel viewModel)中改变了视图 但它没有在RelayCommand中执行
<UserControl.Resources>
<cvm:CateringMenuViewModel x:Key="menu"/>
</UserControl.Resources>
<Border Grid.Row="2" Margin="10, 5" BorderBrush="Black" CornerRadius="8" BorderThickness="2">
<Button DataContext="{Binding Source={StaticResource menu}}"
Command="{Binding ChangePageCommand}"
CommandParameter ="{Binding PageViewModels[2]}"/>
</Border>
public class FillOrderViewModel : ViewModelBase, IUserContentViewModel
{
public FillOrderViewModel() {}
public string Name
{
get
{
return "Fill Order";
}
}
}
<UserControl.Resources>
<cvm:FillOrderViewModel x:Key="fill"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource fill}}">
<DataGrid Margin="405,100,395,110" >
</DataGrid>
</Grid>
轻松回答here
答案 0 :(得分:2)
Kirenenko's answer您有两个独立的CateringMenuViewModel
键入
时<cvm:CateringMenuViewModel x:Key="menu"/>
您告诉WPF创建CateringMenuViewModel
的新实例并为其指定&#34; menu&#34;的键/名称/标识符,因此您在CateringMenuView
中创建了一个副本,在NewRegularOrderView
中创建的第二个副本。当然,更改一个CurrentUserControl
属性不会影响另一个。
这种情况有两种常见的解决方案。
使用某种形式的事件系统让NewRegularOrderViewModel
广播某种消息,让CateringMenuViewModel
侦听这些类型的消息,并在CurrentUserControl
时更改CateringMenuViewModel
听到一个。
将NewRegularOrderViewModel
(或方法委托)传递给ChangePageCommand
,以便它可以直接调用{{1}}。 Korenenko的回答是试图向您展示一个解决方案。
就个人而言,在大多数情况下,如果可能的话,我更喜欢#1这样的东西,尽管#2在大多数情况下也是可以接受的。
我发现我的大多数WPF应用程序都使用了某种消息传递系统,因此在这种情况下使用它是有意义的,你希望一个ViewModel改变另一个ViewModel它没有任何直接的引用至。如果您有兴趣,我会写一些关于here或here的例子。
答案 1 :(得分:1)
问题在于您正在调用CateringMenuViewModel
的两个不同实例。您必须为NewRegularOrderViewModel提供其父viewModel(在您的情况下为CateringViewModel)的实例,以使用相同的DataContext实例来调用相同的命令。
在 CateringMenuViewModel :
中PageViewModels.Add(new NewRegularOrderViewModel(this)); <- add this
PageViewModels.Add(new NewDeliveryComOrderViewModel());
PageViewModels.Add(new FillOrderViewModel());
在 NewRegularOrderViewModel :
中public CateringMenuViewModel Parent;
public NewRegularOrderView(): this(null)
{
}
public NewRegularOrderView(CateringMenuViewModel _Parent) {
Parent = _Parent;
}
private ICommand _changePageCommand;
public ICommand ChangePageCommand
{
get {
if (_changePageCommand == null)
{
_changePageCommand = new RelayCommand(
p => ChangeViewModel((IUserContentViewModel)p),
p => this.CanChangePageCommand);
}
return _changePageCommand;
}
}
bool CanChangePageCommand
{
get { return true; }
}
private void ChangeViewModel(IUserContentViewModel viewModel)
{
Parent.CurrentUserControl = viewModel;
}
在 NewRegularOrderView :
中<Button Command="{Binding ChangePageCommand}"
CommandParameter ="{Binding Parent.PageViewModels[2]}"/>
Datacontext
在这里被压制,因为它指向你的NewRegularOrderViewModel。
我没有任何编辑就完成了这项工作,如果您有任何疑问或失败,请告诉我。