none
Can I Subscribe in Shell.xaml.cs using EventAggregator?(No mvvm,only MEF and EventAggregator)

    Question

  • My senario is here.I have lots of xaps in my solution.every single xap publish a event,I wanna detect it in shell.xaml.cs.Then I can download another xap into the shell.xaml.For example,I have a TreeList.xaml in my Tree.xap like this.

            private IEventAggregator eventAggregator { get; set; }
    
            public TreeList()
            {
                InitializeComponent();
                this.eventAggregator = new EventAggregator();
            }
    
            public void TreeList_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) 
            {
    
                TreeItem treeitem = new TreeItem();
                treeitem.SelectedItemName = ((IDeviceBase)e.NewValue).Name;
    
                if (!string.IsNullOrEmpty(treeitem.SelectedItemName))
                    eventAggregator.GetEvent<TreeSelectedEvent>().Publish(treeitem);
            }
        }


    then,I wanna detect the change of the treeitem.SelectedItemName property(lcoated in Main.Infrastructure)in shell.xaml.cs,then I can download the

    SelectedItemName.xap into the Shell.xaml.so I subcribe in shell.xaml.cs like this,

        [Export("Controls", typeof(FrameworkElement))]
        public partial class Shell : UserControl, IPartImportsSatisfiedNotification,INotifyPropertyChanged
        {  
          public Shell()
            {
                InitializeComponent();
    
                catalogs = new AggregateCatalog();
                catalogs.Changed += new System.EventHandler<ComposablePartCatalogChangeEventArgs>(catalog_Changed);
                _container = new CompositionContainer(catalogs);
                _container.ComposeParts(this);
    
            }
    
            public Shell(IEventAggregator eventAggregator)
                : this()
            {
                this.eventAggregator = eventAggregator;
            }
    
    
            public void TreeSelectedEventHandler(TreeItem treeitem)
            {
                if(treeitem.SelectedItemName!=null)
                                         catalogs.Catalogs.Add(CreateCatalog("TsWorkSpace.xap"));
            }
    
    
    
            public string SelectedItemName
            {
                get
                {
                    return _selectedname;
                }
    
                set
                {
                    _selectedname = value;
    
                    TreeSelectedEvent TreeSelectedEvent = eventAggregator.GetEvent<TreeSelectedEvent>();
    
                    if (subscriptionToken != null)
                    {
                        TreeSelectedEvent.Unsubscribe(subscriptionToken);
                    }
    
                    //subscriptionToken = TreeSelectedEvent.Subscribe(TreeSelectedEventHandler, ThreadOption.UIThread, false, FundOrderFilter);
                    subscriptionToken = TreeSelectedEvent.Subscribe(TreeSelectedEventHandler, true);
                }
            }

    this is the app.xaml.cs where I create the instance of shell
        public partial class App : Application
        {
            
            IEventAggregator eventAggregator{get;set;}
    
            private void Application_Startup(object sender, StartupEventArgs e)
            {
                this.eventAggregator = new EventAggregator();
                this.RootVisual = new Shell(eventAggregator);
            }
    
         }
    



    please ignore the codes in call back methord,I set the breakpoint,but nothing is passed from the click behavior in tree.xap.I don't why?can anyone help me?



    Tuesday, June 14, 2011 6:15 AM

Answers

  • Without reading the link yes the easiest solution is to wrap your eventaggreator in a static class \ singleton pattern.

     

    Thursday, June 16, 2011 10:15 AM

All replies

  • You are creating a new instance of the EventAggregator so you're ending up with 2 instances which don't communicate.

    The eventaggregator is designed to used as a singleton.

    You're getting this correctly with how you are instantiating your shell. In your treelist however use the ServiceLocator to get the instance of EventAggregator.

    i.e.

    _eventAggregator = _bootStrapper.Container.TryResolve<IEventAggregator>();

    Tuesday, June 14, 2011 11:11 AM
  • namespace TsSiteMap
    {  
        [Export("Controls",typeof(FrameworkElement))]
        public partial class TreeList:UserControl
        {
    
            private IEventAggregator eventAggregator { get; set; }
    
            public TreeList()
            {
                InitializeComponent();
                
            }
    
            public void TreeList_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) 
            {
    
                TreeItem treeitem = new TreeItem();
                treeitem.SelectedItemName = ((IDeviceBase)e.NewValue).Name;
    
                this.eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
    
                if (!string.IsNullOrEmpty(treeitem.SelectedItemName))
                    eventAggregator.GetEvent<TreeSelectedEvent>().Publish(treeitem);
            }
        }
    }
    I changed my tree.xaml.cs in tree.xap..and I found when the eventhandler is trigged,the eventaggregator is null.

    Tuesday, June 14, 2011 10:17 PM
  • I'm not sure whether you're using the bootstrapper part of prism to set everything up. This would automatically make the eventaggregator available to be found via the servicelocator.

    Wednesday, June 15, 2011 5:41 AM
  • oh,I don't use that,I just initialize the shell.xaml in app.cs..

    Wednesday, June 15, 2011 6:26 AM
  • because I don't wanna use unity,I wanna download the xap dynamic,so...bootstrapper looks like initialize all the module at first..

    Wednesday, June 15, 2011 6:28 AM
  • You'll need to somehow expose your eventaggregator as a singleton to anything wanting to use it then.

    Whether that is via unity or some other mechanism is up to you.

    Wednesday, June 15, 2011 7:12 AM
  • Hi,

    Wrong with Unity Load On Demand or background, When avarible etc.

    Seems like the hard problem was solved by Prism Team.

    The Shell is notified when the module is downloaded and initialized by subscribing to the ModuleManager.LoadModuleCompleted event.

    this.moduleManager.LoadModuleCompleted += this.ModuleManager_LoadModuleCompleted;

    void ModuleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)
    {
        this.moduleTracker.RecordModuleLoaded(e.ModuleInfo.ModuleName);
    }

     

    Wednesday, June 15, 2011 9:56 AM
  • thai, like most other threads please read what the OP's requirements are.

    Wednesday, June 15, 2011 10:06 AM
  • sledge70,thank you for your patient.I knew now the reason is that I don’t have a global instance.But here is my question,CompositePresentationEvent itself is a container for hold all the events that be published.if you wanna subcribe,you just need a key(a new instance,somehow)to enter the container.So,I don't know why I have to need the same insatance.

    Besides,I found this,http://blogs.microsoft.co.il/blogs/shimmy/archive/2011/04/09/eventaggregator-shortener.aspx looks like I should create a static class for eventaggregator.


    Am I Wrong or right?

    best regards!

    Wednesday, June 15, 2011 9:11 PM
  • Without reading the link yes the easiest solution is to wrap your eventaggreator in a static class \ singleton pattern.

     

    Thursday, June 16, 2011 10:15 AM
  • yeah,singleton.Thank you for your help,you gave a light.Smile

    Thursday, June 16, 2011 8:42 PM