【问题标题】:Navigate between UserControls with Event Aggegator使用事件聚合器在用户控件之间导航
【发布时间】:2015-12-23 08:27:41
【问题描述】:

我有一个 MainWindow,我通过单击菜单在 UserControls 之间导航,它工作正常。

我正在使用以下模式:

https://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/

在其中一个用户控件中有一个按钮。通过单击此按钮,我想导航到另一个用户控件。

我该怎么做?

主视图

<UserControl.Resources>
    <DataTemplate DataType="{x:Type cvm:FirstViewModel}">
        <cv:FirstView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type cvm:SecondViewModel}">
        <cv:SecondView/>
    </DataTemplate>
    <cvm:MainViewModel x:Key="main"/>
</UserControl.Resources>

<Grid DataContext="{Binding Source={StaticResource main}}">
    <Border Grid.Row="0">
        <Menu Height="58">
             <ItemsControl ItemsSource="{Binding PageViewModels}" Width="289" Height="58">
                 <ItemsControl.ItemTemplate>
                     <DataTemplate>
                         <TextBlock>
                             <Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay, Source={StaticResource main}}" CommandParameter="{Binding}" TextDecorations="{x:Null}">
                                 <InlineUIContainer>
                                     <TextBlock Text="{Binding Name}"/>
                                 </InlineUIContainer>
                             </Hyperlink>    
                         </TextBlock>
                      </DataTemplate>
                 </ItemsControl.ItemTemplate>
             </ItemsControl>
        </Menu>
    </Border>       
    <Border Grid.Row="1" >
        <ContentControl Content="{Binding CurrentUserControl}"/>
    </Border>
</Grid>

MainViewModel

public class MainViewModel : ViewModelBase
{
        public MainViewModel()
        {
            PageViewModels.Add(new FirstViewModel());
            PageViewModels.Add(new SecondViewModel());

            // 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;
            }
        }
    }

第二视图

<Grid Background="Blue">
    <Button /> <!-- Going to ThirdView?????????-->
</Grid>

【问题讨论】:

    标签: c# wpf user-controls eventaggregator


    【解决方案1】:

    您必须通过按钮拨打ChangePageCommand

    <Button DataContext="{Binding Source={StaticResource main}}"
            Command="{Binding ChangePageCommand"} 
            CommandParameter="{Binding PageViewModels[2]}">
    

    我假设您的FirstViewModel 存储在PageViewModels[0],您的SecondViewModel 存储在PageViewModels[1]

    您还必须创建一个指向您的ThirdViewModelThirdView 链接,作为您的其他两个视图/视图模型:

    <UserControl.Resources>
        ...
        <DataTemplate DataType="{x:Type cvm:ThirdViewModel}">
            <cv:ThirdView/>
        </DataTemplate>
    </UserControl.Resources>
    

    作为建议,您可以在代码开头设置 UserControl DataContext,而不是在任何 UIElement(在您的情况下为按钮和网格)中使用它,如下所示:

    <UserControl.DataContext>
        <cvm:MainViewModel />
    </UserControl.DataContext>
    

    编辑>>>>

    忘了说您还必须将您的 ThirdViewModel 添加到您的 PageViewModels 集合中:

    PageViewModels.Add(new ThirdViewModel());
    

    【讨论】:

    • 它不起作用,但我们非常接近。如果我写 CommandParameter="{Binding PageViewModels[3]}" (为空),按钮是 isEnable = '"false",所以投标有效
    • @Cantinou 它的 PageViewModels[2] -> 你的 ThirdViewModel。不是[3]。你检查过编辑吗?
    • 所以,查看 Visual Studio 的输出控制台并检查是否某些绑定失败。如果我不知道失败的原因,我无法帮助您。
    • 我看不出问题所在。 CurrentUserControl 在 CurrentUserControl = PageViewModels .FirstOrDefault(vm => vm == viewModel);
    • @Cantinou ContentControl 完全没有变化吗?并且没有绑定失败吗?您的 ThirdView UserControl InitializeComponent() 被调用了吗?
    【解决方案2】:

    我终于有了解决办法。

    我在 Prism 6 中使用事件聚合器。

    首先我创建一个单例。

    internal sealed class ApplicationService
        {
            private ApplicationService() { }
    
            private static readonly ApplicationService _instance = new ApplicationService();
    
            internal static ApplicationService Instance { get { return _instance; } }
    
            private IEventAggregator _eventAggregator;
            internal IEventAggregator EventAggregator
            {
                get
                {
                    if (_eventAggregator == null)
                        _eventAggregator = new EventAggregator();
    
                    return _eventAggregator;
                }
            }
        }
    

    然后public class GoToThird : PubSubEvent&lt;TEvent&gt; { }

    MainViewModel 我订阅了活动并添加了我的ThirdViewModel()

    public class MainViewModel : ViewModelBase
    {
            protected readonly IEventAggregator _eventAggregator;
    
            public MainViewModel(IEventAggregator eventAggregator)
            {
                PageViewModels.Add(new FirstViewModel());
                PageViewModels.Add(new SecondViewModel(ApplicationService.Instance.EventAggregator)));
    
                PageViewModels.Add(new ThirdViewModel());
    
                // Set starting page
                CurrentUserControl = PageViewModels[0];
    
                this._eventAggregator = eventAggregator;
            }
    
            private void GoToThird()
            {
                CurrentUserControl = PageViewModels[2];
            } 
    }
    

    最后我将活动发布到SecondViewModel()

    public class SecondViewModel
        {
    
            protected readonly IEventAggregator _eventAggregator;
    
            public SecondViewModel(IEventAggregator eventAggregator)
            {
                this._eventAggregator = eventAggregator;
    
            }
    
    
    
            private void Go()
            {
                _eventAggregator.GetEvent<GoToThird>().Publish();
            }
    
    
            private ICommand goToThirdCommand;
    
            public ICommand GoToThirdCommand
            {
                get
                {
                    return goToThirdCommand ?? (goToThirdCommand = new RelayCommand(p => this.Go(), p => this.CanGo()));
                }
            }
    
            private bool CanGo()
            {
                return true;
            }
    }
    

    非常感谢 Rachel 和 Kirenenko

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      • 2015-03-22
      • 1970-01-01
      相关资源
      最近更新 更多