WPF PRISM event subcriptions not dying - wpf

I have a PRISM RegionManager with a couple of region - a Ribbon region on the top, and a main content region for my view underneath it - fairly basic.
The app starts with a "home" view in the main content area. When I click a button on the Ribbon, I inject a second view into the content area and navigate to it in the region manager. When I click a button on this view, it should be removed and the original view should be shown.
I'm currently doing this using the RegionManager.Add() method to manually add the second view. When I want to remove it, I publish an event which is consumed by a manager class that gets the current active remove, calls Remove() on the Region Manager for it, and then navigates back to the original view.
This all works great, except that when the second view is left alive after I call Remove(), and keeps a handle onto any subscriptions that it made during its lifetime! I've tried calling Subscribe explicitly with false for weak event references, but this is the default anyway, and it didn't help. I've tried both types of creating the view (discovery and injection) and removing the view via Remove and Deactivate. None of them helped. This is a real problem as when I want to create the same view in the future (a new instance of that view), I'm left with several instances of them, all subscribing to the same events, even though some of those instances were removed ages ago from the Region Manager.
Do I need to manually unsubscribe from every event that I subscribe to in my views (highly undesirable)? Or is there some way that I can dispose of the control / mark it as deactivated so that its subscriptions get removed?
I get the feeling that I'm doing something silly here but it's got me completely stumped.
Thanks

This is a known issue. There is a bug in the eventAggregator code. Take a look at the following blog and the suggested hack to overcome it
http://greenicicleblog.com/2010/04/28/prism-event-aggregator-more-leaky-than-it-seems/
Hope this helps

Related

Angular and Google tag manager (GTM) gtm.click

I am running into a problem, and I cannot seem to find a fix for it. The situation is as follows the marketing department wants to integrate GTM. Which is fine as they want to have full control over the different third party providers they wish to integrate. But for this to happen they would like to have the ability to track all clicks on a page.
And they came back to me that currently no click events are being tracked with the current configuration within GTM. At first the thought was that events were not propagating (bubbling) upwards. But having tested this myself by binding a event listener to the document (click) (see below) all div, buttons etc. with an ng-click directives did reach this handler without problems.
document.addEventListener("click", function(event){
console.dir(event.target);
});
So my assumption was that there was something wrong with the configuration but after looking at the configuration (one I created myself which looks as follows):
I still could not get it to work. Buttons that already use angulartics - https://luisfarzati.github.io/angulartics/ to send an event to the GTM container work as expected:
Download
Only the catch all click events (or any filter on it like purely looking at button clicks) does not. Now after looking at it a little more it seems GTM expects the gtm.click _event to happen. But I can't figure out (gazing through the gtm.js file) how they bind to all click events within the document (there is a click binding on the document after initialization but I am unsure if this is GTM or something from angular). And even if so I have placed many breakpoints within this file which seemingly could be related to it but none of them triggered when something was clicked.
So my question is, has anybody got experience combining angularjs with angulartics and GTM while having it catch all click/touch/mousedown etc. events and send these to GTM?
Make sure that you pusblished GTM container after you made some changes. Use "Publish Now" or "Preview and Debug" buttons inside of GTM interface(top-right corner).
Because according to your tag config this tag should fire every time when user clicks something on the website.
Regarding to "gtm.click" - this GTM-event will fire every time, when user clicks something on the website.
On the screenshot you may see, how it looks like in GTM debug mode("Preview and Debug") when user clicking on somethig at web-page, when GTM click listener turned on(like in your tag).
May be some relevant articles from my website about tracking of buttons/links on GTM will help you too:
http://konygin.net/gtm/tracking-links-en/
http://konygin.net/gtm/tracking-buttons-en/
My problem turned out to be that the person (from marketing) who gave me the html GTM tags (noscript / script) did not copy it properly (or something went wrong when it was pasted within JIRA). And after I copied it directly (having gotten access to the GTM admin panel) it worked as I would expect it to work.
Seeing as I debugged it by trying to only have one index.html with purely a button in it. Even at that point the tracker did not work and I became suspicious why that was happening as there was no angular code any more that could cause the problems.
Lesson learned, next time copy code yourself when you need it to make sure it does not get corrupted along the way :/

Should Prism RequestNavigate work with no UI?

I have a Prism 4.0 enabled WPF application that uses RequestNavigate extensively, and it is working well. I have a scenario where I would like to render part of my UI to an image and store it for later use from a Windows service. I already know how to use RenderTargetBitmap to generate the image, but whenever my code tries to call RequestNavigate, nothing happens. I am calling the bootstrapper, so I would expect that all of the types are loaded, but it just is not working. Can anyone tell me if this should even be possible? Is there anything inherent to RequestNavigate that prevents it from working when there is no UI present?
Individual steps:
First, I call Run on my MefBootstrapper. This loads up all of the assemblies into the AggregateCatalog.
Then, I use MEF CompositionContainer.GetExportedValue to create a WPF UserControl that has a single ContentControl that is assigned a RegionManager.RegionName. This always creates the initial UserControl just fine.
Finally, I call MefRegionManager.RequestNavigate with the region name on my UserControl and the path to another UserControl that I want it to load. This fails to load the UserControl that I am attempting to navigate to.
If these are the only steps that I follow, then the final UserControl fails to load whether I am running from a Windows Service or from within my WPF application. However, if I call SetRegionManager to explicitely add the region from my host UserControl before calling RequestNavigate, then the last UserControl will load properly, as long as the code is run from within the WPF application. If this same code is run from my Windows service, then it still does not load.
RequestNavigate is exactly that, a request to navigate to a loaded (but inactive) region. It won't do any loading itself. You need to separately manage the loading of views (including views within views).
If your nested user control is only over loaded within the parent, and you don't need to manage it at runtime, then you can use ViewDiscovery. You register all the views in advance, and then when the region is created, it looks for (and loads) all the nested views. If you need to manage the views at runtime, switch them in and out, etc, then you can use ViewInjection.
For ViewDiscovery, in the Initialize method of the ModuleInit class in your module, insert the following line:
_regionManager.RegisterViewWithRegion("RegionNameOfYourNestedControl",
() => this.container.Resolve<NestedUserControl>());
Then when your region is loaded, the NestedUserControl will automatically be loaded into your ContentControl (region).
For more detail on ViewDiscovery, ViewInjection and UI composition, have a read of the prism documentation

Navigation application - Forces a page at startup

I have a silverlight navigation application where I load and initialize a lot of things in the MainPage.aspx loading.
All the Pages (views) are dependent on the loading of that data.
But really often my users add an internet shortcut on their desktop for my application. but the link often points to a specific page like that :
http://myServer/MyApp/default.aspx#/TheView
I want to force the users to go to the "Default" view (and ignore the #/view parameter) when the application Starts up.
Whats the best way I can do that?
I don't think it's a good idea to 'avoid' links. You should construct the application in a way when it's not a problem.
For example you can send a message from your main logic when everything loaded, and until that message you can disable the appropriate UI (while waiting for data). Messenger (or EventAggregator in Prism) is a publisher-subscriber pattern to achive communication between components without reference to each other. If you don't know it yet, take a look at MVVMLight Messenger or Prism EventAggregator
But if the first option is not okay for you, you can play with the Frame control's JournalOwnership property:
http://msdn.microsoft.com/en-us/library/system.windows.controls.frame.journalownership(v=vs.95).aspx
http://msdn.microsoft.com/en-us/library/system.windows.navigation.journalownership(v=vs.95).aspx
OwnsJournal is your value, because it does not integrate with the browser journal and the url stays the original so your users can't bookmark a 'sub page'.
You can also implement your own journal mechanism.
Another :), but pretty ugly option would be if you track the first page load (in OnNavigatedTo Page events for example), and at the very first request you manually navigate to the main page. Or in the App.xaml.cs, when application starts up you forward the page request.
But I recommend the first one.

PageFunction not being disposed of causes crash

I have a WPF "wizard" where I am using PageFunction objects to display the various pages in the wizard. Several of these pages use references to objects in other assemblies within the application so the user can select "packages" they want to include in a generated ouput. In the page function, I have the keep alive flag set to true so that when the user presses cancel or finish in the wizard I can capture the wizard results and the corresponding data the user selected.
The problem is that the wizard pages never go away even after the scope in which they were created has been exited, Thus, when I try to remove one of the referenced objects that the wizard was databound to from a collection, it causes the wizard page to throw an exception. I cannot seem to find a way to correct this issue without setting the KeepAlive flag to false, but this breaks the ability to capture the user data from the wizard.
Any ideas?
Thanks!
I have something very similar (if not the same). A wizard created with a navigation window and a set of pagefunction pages to collect data. Some of the pagefunction pages are even pulled from assemblies in the application folder but I have never had this problem. Can you be more specific on the problem? How do you try to remove the referenced objects? Can you post some code so I can look at it?

Multiple calls to data service from SL3?

I have an SL3 that makes asynchronous calls to a data service. Basically, there is a treeview that is bound to a collection of objects. The idea is that as a user selects a specific treeviewitem, a call is made to the data service, with a parameter specific to the selected treeviewitem being passed to the corresponding web method in the data service. The data service returns data back to the SL3 client, and the client presents the data to the user.
This works well. The problem is that when users start to navigate through the treeview using the arrow keys on their keyboard, they could press the down arrow key, for example, 10 times, and 10 calls will be made to the data service, and then each of the 10 items will be displayed to the user momentarily, until finishing with the data for the most recently selected treeview item.
So - onto the question. How can I put in some form of delay, to allow someone to navigate quickly through a treeview, then, once then stop at a certain treeviewitem, a call is made to the data service?
Thanks for any suggestions.
Chris
use Rx for silverlight
As suggested by funwithcoding, you could try using the Reactive Extensions for .Net (Rx), I've not used it myself but from what I hear it would do what you're after.
However if you don't feel like you want to / have time to learn Rx etc. maybe look at using a DispatcherTimer to create a slight delay in you Treeview selected event, before you call the service to retrieve the data.

Resources