View,ViewModel和DataContext

时间:2016-01-25 07:49:40

标签: c# wpf model viewmodel eventaggregator

为了解决我的应用程序中的导航问题,我使用了一个事件聚合器来解决问题,但创建了另一个。

要在不同的UserControl之间导航,我使用了Rachel的代码,你可以找到here,这些代码工作正常,直到我做了一些更改。

在我的屏幕一侧,我有一个主菜单(HomeViewModel()),点击我在UserControls之间切换的项目,在每个UserControls中有另一个菜单栏,我可以在其他用户控件之间切换

但是第二个菜单(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>

2 个答案:

答案 0 :(得分:3)

这里有两个问题。

  1. 首先,您不想手动设置UserControl的.DataContext,因为您要使用CateringMenuViewModel中的PageViewModels[1],而不是创建它的新实例。

    所以一定要删除代码行

    DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
    
  2. 第二个问题是您的活动未被解雇的原因。我看了你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!