为了解决我的应用程序中的导航问题,我使用了一个事件聚合器来解决问题,但创建了另一个。
要在不同的UserControl之间导航,我使用了Rachel的代码,你可以找到here,这些代码工作正常,直到我做了一些更改。
在我的屏幕一侧,我有一个主菜单(HomeViewModel()
),点击我在UserControls之间切换的项目,在每个UserControls中有另一个菜单栏,我可以在其他用户控件之间切换
但是第二个菜单(CateringMenuViewModel()
)不再起作用了。显示UserControl但是当我在菜单栏中单击时没有发生任何事情。
第一眼我认为是因为没有DataContext。 所以我在后面的代码中添加了它:
public CateringMenuView()
{
InitializeComponent();
this.DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
}
但它仍然无效。
我不明白,属性Name
是有界限的,因为名称显示在菜单中,但命令ChangePageCommand
不是。
public class HomeViewModel : ObservableObject
{
#region Fields
private ICommand _changePageCommand;
private IPageViewModel _currentPageViewModel;
private List<IPageViewModel> _pageViewModels;
#endregion
public HomeViewModel()
{
// Add available pages
PageViewModels.Add(new HomeOrderViewModel());
PageViewModels.Add(new CateringMenuViewModel(ApplicationService.Instance.EventAggregator));
PageViewModels.Add(new HomeAdminViewModel());
// Set starting page
CurrentPageViewModel = PageViewModels[0];
}
#region Properties / Commands
}
public class CateringMenuViewModel : ObservableObject, IPageViewModel
{
protected readonly IEventAggregator _eventAggregator;
public CateringMenuViewModel(IEventAggregator eventAggregator)
{
this._eventAggregator = eventAggregator;
PageViewModels.Add(new NewRegularOrderViewModel(ApplicationService.Instance.EventAggregator));
PageViewModels.Add(new NewDeliveryComOrderViewModel());
PageViewModels2.Add(new FillOrderViewModel());
// Set starting page
CurrentUserControl = PageViewModels[0];
this._eventAggregator.GetEvent<GoToFillOrder>().Subscribe(GoToFillOrder);
}
public string Name
{
get
{
return "Catering";
}
}
public string imageSource
{
get
{
return "catering.ico";
}
}
#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);
var x = this.GetHashCode();
}
#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;
}
}
private void GoToFillOrder(int i)
{
CurrentUserControl = PageViewModels2[0];
}
}
<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>
</UserControl.Resources>
<Grid Margin="5">
<Grid>
<StackPanel>
<Menu>
<MenuItem Header="New Order">
<ItemsControl ItemsSource="{Binding PageViewModels}" Width="168" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}" CommandParameter="{Binding}" TextDecorations="{x:Null}">
<InlineUIContainer>
<TextBlock Text="{Binding Name}"/>
</InlineUIContainer>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</MenuItem>
</Menu>
</StackPanel>
</Grid>
<ContentControl Content="{Binding CurrentUserControl}"/>
</Grid>
答案 0 :(得分:3)
这里有两个问题。
首先,您不想手动设置UserControl的.DataContext
,因为您要使用CateringMenuViewModel
中的PageViewModels[1]
,而不是创建它的新实例。
所以一定要删除代码行
DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
第二个问题是您的活动未被解雇的原因。我看了你question's version history中的代码,我没有看到你在任何地方播放这个活动。
这行代码是正确的说“任何时候广播GoToFillOrder
类型的事件,运行方法GoToFillOrder
”
_eventAggregator.GetEvent<GoToFillOrder>().Subscribe(GoToFillOrder);
然而,我没有看到任何实际广播该事件的代码。您需要一行代码,如下所示,在整个应用程序中广播GoToFillOrder
消息:
_eventAggregator.GetEvent<GoToFillOrder>().Publish();
答案 1 :(得分:1)
我终于找到了解决方案。
在CateringMenuView()
,我已取代
<Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}"
CommandParameter="{Binding}"
TextDecorations="{x:Null}">
通过
<Hyperlink Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding}"
TextDecorations="{x:Null}">
非常感谢Rachel!