2016-01-25 4 views
0

Чтобы решить проблему с навигацией в моем приложении, я использовал агрегатор событий, который решил проблему, но создал другую.View, ViewModel и DataContext

Чтобы перемещаться между различными UserControls, я использовал код Rachel, вы можете найти here, который работал нормально, пока не внес некоторые изменения.

На боковой стороне экрана у меня есть Главное меню (HomeViewModel()), нажав на элементы, которые я переключаю между UserControls, и в каждом из этих 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> 
+3

Сократите ваш код немедленно! Оставьте только описание вашей проблемы! –

+1

Для активиста, только потому, что есть _code present_, не обязательно означает, что это хороший вопрос, так как Кирилл упоминает – MickyD

+0

@ Микки, может быть полезно воспроизвести проблему, чтобы использовать существующий код вместо того, чтобы пытаться создать подобную ситуацию только из описания. –

ответ

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}"> 

Большое спасибо Рейчел!

3

Два проблемы здесь.

  1. Во-первых, вы не хотите, чтобы установить .DataContext вашего UserControl вручную, потому что вы хотите использовать 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(); 
    
+0

Событие запускается в NewRegularOrderViewModel(). И он отлично работает. – Cantinou

+0

Итак, как связаны «CateringMenuViewModel (ApplicationService.Instance.EventAggregator)» и «CateringMenuView()»? Я не могу установить соединение в XAML, потому что у параметра «CateringMenuViewModel» есть аргумент. – Cantinou

+0

@Cantinou Ваш 'DataTemplate' поставляет его. Ваш неявный DataTemplate говорит * «всякий раз, когда вы сталкиваетесь с« CateringMenuViewModel »в дереве пользовательского интерфейса, рисуете его с помощью« CateringMenuView »*, и он автоматически устанавливает' .DataContext' за «CateringMenuView» в объект «CateringMenuViewModel» – Rachel

Смежные вопросы