When to Call ViewModel.LoadData? - silverlight

I have a WP7 Silverlight app that displays a bunch of data using Pivot. When first creating the project, the Visual Studio template calls ViewModel.LoadData in Page_Loaded:
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
App.ViewModel.LoadData();
}
However on MSDN it says you should use OnNavigatedTo instead of Page_Loaded, because OnNavigatedTo is called only once when a page becomes active, while Page_Loaded is called everytime an item is added to the page's visual tree. The MSDN article is for Silverlight 4 instead of for Silverlight Windows Phone though.
You override the OnNavigatedTo method
to examine the navigation request and
prepare the page for display. For
example, you can load the requested
data and enable or disable visual
elements.
Typically, you use the OnNavigatedTo
method instead of creating an event
handler for the Loaded event. The
OnNavigatedTo method is preferable
because it is only called once for
each time the page becomes active. The
Silverlight framework raises the
Loaded event each time the element is
added to the visual tree, which
potentially can happen more than once
when activating a page. The
OnNavigatedTo method is called for
each request, even when the page is
retrieved from the cache. You should
include in this method code that must
be executed for each request rather
than placing that code in the Page
constructor.
Is there any reason why the Visual Studio Pivot template calls ViewModel.LoadData in Page_Loaded?

I think you're confusing LayoutUpdated and Loaded.
Loaded should only get called once each time the page is displayed.
Loading data specific to a page after that page has been constructed is a simple way of working with data tied to a specific page. My guess is that the default templates use this as it's simple to understand and learn from.
Update
The article in MSDN that you refer to is for Page.Loaded. WP7 does not use Page instead it uses PhoneApplicationpage.
Having worked with WP7 for over a year and created dozens of apps, I've never seen the Loaded event called multiple times in a WP7 app.

Related

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

Silverlight redirecting between project pages

I am having a my problem is I can not redirect my page in silverlight like most of people who are not familiar with this technology .
I design a login page first and if password is correct I want it to direct to MainPage.xaml
as you can see I tried methods which are commented already it did not work . I searched in this web page there are some posts about this problem but I could not solve please help me .
when i try that one;
Uri target = new Uri("MainPage",UriKind.Relative);
NavigationService.Navigate(target);
error message : Object reference not set to an instance of an object.
actually we found a solution with my friend ;
instead of directing a web page , when code goes into if block we are changing the content of page with {this.Content = new MainPage() ; } method and it is working .But System.Windows.Browser.HtmlPage.Window.Navigate(target) this one is directing us same login page or pages like www.---.com outside normal html pages .
Normally you need to use the NavigationService to do this:
NavigationService.Navigate(new Uri("/MainPage", UriKind.Relative));
The NavigationService is a property on the Page object so it will be available in the Login code-behind.
However, after you mentioned that you've "already done this" I realized the issue. Silverlight Navigation uses a Frame control. This Frame control lives in MainPage.xaml for the default project. So you're not navigating inside the frame, but you want to change the entire screen to a different one and do so without the Navigation services built into Silverlight.
I'd suggest you either (a) have the Login run as a page inside of the Frame on MainPage (you can load or unload the links on the top based on if the user is authenticated) or (b) don't use the Navigation for the remainder of the application and use a framework like Caliburn.Micro to handle all the Navigation between views.

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.

Windows Phone 7 - Using the Application bar and Prism (or MVVM)

I am playing around with the WP7 SDK and the Prism for WP7 beta and have come across a problem I can't figure out (or even a workaround for).
First of all, I'm new into WPF/Silverlight/WP7 and Prism, so I could be overlooking something very obvious.
So I have a Shell page that has my region that is used to hold my content pages, and all of this is working great! Now my problem is that I have a settings control that will allow the users to edit the settings of the application (names, locations, etc). Now I can get this page to work with no problems by having a button on one of my controls that will transition the region manager to the control.
However, I would like to use the application bar on the phone to have the button, but I cannot for the life of me figure out how to get access to my model object from within the page that is opened by the Application bar click. I can only do a NavigationService.Navigate() to a settings page, but the PhoneApplicationPage objects in WP7 do not allow injection on the constructors (the constructors must be parameterless) so I cannot pass in the object instance in that way.
So my question is, how can I access (or pass) objects between pages or controls?
Thanks!
In the examples they use this technique to set the data context of a form after it is navigated to from another form:
NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
FrameworkElement root = Application.Current.RootVisual as FrameworkElement;
root.DataContext = some_object;

What is the difference between NavigationService.Navigate() method and PhoneApplicationFrame.Source property?

Taken from Exercise 1: Creating Windows Phone Applications with Microsoft Visual Studio 2010 Express for Windows Phone
Task 3: Step 9
// navigate
this.NavigationService.Navigate(new Uri("/PuzzlePage.xaml", UriKind.Relative));
Note:
The PhoneApplicationPage class provides methods and properties to navigate to pages through its NavigationService property. You can call the Navigate method of the NavigationService and pass the URI for the page as a parameter. You can also use the GoBack and GoForward methods to navigate backward or forward in the navigation history. The hardware back button also provides backward navigation within an application. The event handler shown above uses the NavigationService to go to the PuzzlePage.xaml page.
Task 4: Step 3
(RootVisual as Microsoft.Phone.Controls.PhoneApplicationFrame).Source =
new Uri("/ErrorPage.xaml", UriKind.Relative);
Note:
...
Whenever you set the Source property to a value that is different from the displayed content, the frame navigates to the new content.
...
What are the differences and similarities of both techniques?
Essentially, they both do the same thing.
NavigationService.Navigate is a native Silverlight navigation service to allow the asynchronous navigation from one xaml file to another (eliminating the need to load usercontrols) - there's an excellent little overview here.
The difference is that NavigationService has the ability to go backward and forward in a browser-esque fashion. Setting the Source property of the PhoneApplicationFrame does not.
Still early days and it's probably too soon to make an educated guess as to which you should use.
NavigationService has the advantage of being a Silverlight-native class, however PhoneApplicationFrame.Source is specific to WP.

Resources