问题描述
为了解决我的应用程序中的导航问题,我使用了Event Aggregator(事件聚合器),它可以解决该问题,但是又创建了另一个.
要在不同的UserControls之间导航,我使用了Rachel的代码,您可以找到在这里,在我进行了一些更改之前,一切正常.
在屏幕的一侧,我有一个主菜单(HomeViewModel()
),通过单击在UserControl之间切换的项目,在每个UserControl中都有另一个菜单栏,可在其中切换其他UserControl. /p>
但是第二个菜单(CateringMenuViewModel()
)不再起作用.显示了UserControl,但单击菜单栏中没有任何反应.
乍一看,我认为这是因为没有DataContext.因此,我将其添加到了如下代码中:
public CateringMenuView()
{
InitializeComponent();
this.DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
}
但是它仍然不起作用.
我不明白,属性Name
有很好的边界,因为名称显示在菜单中,但命令ChangePageCommand
却没有.
HomeViewModel
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
}
CateringMenuViewModel
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];
}
}
CateringMenuView
<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>
我终于找到了解决方案.
在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!
In order to solve a navigation issue in my application I have used an Event Aggregator which has solved the problem but has created an other one.
To navigate between different UserControls I used the Rachel's code you can find here which was working fine until I made some changes.
On the side of my screen I have a Main Menu (HomeViewModel()
), by clicking on the items I switch between UserControls and in each of these UserControls there is a another menu bar where I can switch between other UserControls.
But this second menu (CateringMenuViewModel()
) doesn't work anymore. The UserControl is displayed but nothing is happening when I am clicking in the menu bar.
At the first sight I thought it's because there is no DataContext.So I added it in the code behind like this:
public CateringMenuView()
{
InitializeComponent();
this.DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
}
But it still doesn't work.
I don't understand, the property Name
is well bounded because the names are displayed in the menu but the command ChangePageCommand
is not.
HomeViewModel
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
}
CateringMenuViewModel
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];
}
}
CateringMenuView
<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>
I finally found the solution.
In CateringMenuView()
, I have replaced
<Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}"
CommandParameter="{Binding}"
TextDecorations="{x:Null}">
by
<Hyperlink Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding}"
TextDecorations="{x:Null}">
Big thanks to Rachel!
这篇关于View,ViewModel和DataContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!