Sharing viewmodel to multiple views using Caliburn.Micro in WP7 - windows-phone-7

I am currently working on a project which requires multiple views of the same viewmodel. Let me describe this way:
ViewModel: CustomerDetailsViewModel.cs (inherited from Screen class)
View: CustomerDetails.cs (this view has CustomerDetailsViewModel as datacontext and this set automatically by Caliburn.Micro)
View: CustomerInfo.cs (now this is the view where I want to share CustomerDetailsViewModel, which could have some data already modifed via CustomerDetails view)
I am currently using NavigationService to navigate to CustomerInfo view. Is there any way to pass the reference of current viewmodel to the view which user is navigating to in caliburn.micro?
Thanks in advance
idev

Use the attached property cal:Bind.Model="{Binding}" to bind the view to the view model.
See http://caliburnmicro.codeplex.com/wikipage?title=All%20About%20Actions "View First" section.
Alternatively you can also look into the cal:View.Context="MyContext" attached property as described here: http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition "Multiple Views over the Same ViewModel" section.

Add a property or two to your App.xaml.cs. What ever you put in here will persist throughout the lifetime of the application (keep in mind that tombstoning will cause this property's value to be lost though). If you want to pass a ViewModel then setyour associated property in App.xaml.cs to the view model and then when the new page loads have it read from that same property.

Related

Mvc base viewmodel render data within layout

I have created a base viewmodel that all of my view models inherit from. That part is easy.
All views are bound to a viewmodel (all are inherited from the base view model)
Within the OnActionExecuted method I insert a true/false value onto a property within the baseviewmodel depending on some conditions.
From the view side of things. I have a single layout page that some how I want to be able to read the property's value and render a different partial view based on the value.
Is this possible? I dont want to have to add the code to each of the views but I don't think I should be binding the layout to my baseviewmodel either.
If I can stay away from inserting the value into the valuebag that would be great as I need to be able to access these values anywhere in the application via strongly typed names.
what you want probably isnt possible because as you call a view from the controller then first the code inside that view is executed and then the layouts code is executed
to achieve what you are doing you can do 2 things
1. make the logic inside the controller itself and then render the correct view
2.call the layout from the controller giving it the name of the partial view in some property of the model or in the viewbag
Not sure I quite follow the use case, but rather than trying to render out a partial view, have you thought about nesting your layout pages.
I think you should be able to override the layout in the onactionexecuted, so you can set the layout dependant on the bool and that layout will render only the correct option.
Look here for an example:
Nested layout pages with Razor
HTH
Si

How do I create a dynamic page based on a selection?

I am trying to dynamically fill a second panorama page based on what item was selected from the home application screen.
On the application's first start screen there is a listbox if items each with text. If a user taps on an item with text "foobar" a template page should load and the title of the template page should be set to "foobar" and this second panorama page should know that it's data should be related to "foobar".
Is there anyway to do this?
I currently have my MainPage navigate to a new page (DynamicPage.xaml). This navigation is triggered when a ListBox_SelectionChanged event occurs. I have the title text of the DynampicPage.xaml Binding to a TitleText variable that is located in MainPage.xaml.cs. However, when I do this the title of DynamicPage.xaml is ever only set to my initialization value for the titleText variable even though I am updating this variable right before I navigate to the page.
If anyone can provide some help I would be very grateful as I am just a beginner on the WP7 platform. Thanks!
The Binding you're using for the title is only going to update if the TitleText property is a dependency property or if your MainPage is implementing the INotifyPropertyChanged interface so your class can notify the UI when one of its properties changed.
http://windowsphonegeek.com/articles/All-about-Dependency-Properties-in-Silverlight-for-WP7
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.95).aspx
But I think this is not the best way for you to achieve this. For now a much better way is to store your data somewhere in a static class, in the main page's constructor load these data into the listbox, and when the user selected an item, navigate the user to the second page like this:
NavigationService.Navigate(new Uri("/DynamicPage.xaml?Item=" + selectedItem.Id, UriKind.Relative));
When you navigate like this a new instance of DynamicPage is created, and in the OnNavigatedTo method you can access the navigation parameters and populate your page with the selected data. For example:
<controls:Panorama x:Name="MyPanorama" Title="TitleHere">...</controls:Panorama>
Item selectedItem = StaticData.GetItem(NavigationContext.QueryString["Item"]);
MyPanorama.Title = selectedItem.Name.ToUpper();
Description.Text = selectedItem.Description;
This way you can use secondary tiles and toast notifications to directly point to a specific content in your application.
If you're getting to understand the navigation you should definitely use the pattern called Model-View-ViewModel which is about to solve these problems mostly with bindings, but trust me, probably this is the easier way for now.

PRISM: Passing object/events from parent to child View/VM with PopupRegions

We are working with an application that uses prism and MVVM for healthcare tracking operations.
Within this application, we have registered views in primary regions, and scenarios in which clicking on a cell in a grid (in this case a xamdatagrid - Infragistics) will launch another region via the prism region popup behaviors constructs.
So, when we click on the cell, a cellactivation operation in the code behind for that view is called which then calls a method in the view model to .RequestNavigate to the view that is registered for the 'secondary' popup region (thus launching what appears to be a dialog over the existing application).
I am attempting to pass an object from the parent view (the values of the record in the grid) to the child view that is launched in the popup, and have found that none of the expected operations is working.
I have a mediator object that we are using to pass information back from children to parents, but this does not work the other direction because the publish/notify operations for the mediator require the child view to 'already' be instantiated before the parent publishes to pass that information.
I'm finding that the event aggregator structures built into the Prism.Events classes don't appear to be working either (I'm assuming because of the same publish/subscribe issues). I can publish an event through the event aggregator from the parent view and subscribe in the child view, but I have to launch the child view 'twice' in order to get the event tied to the event aggregator operation to actually fire.
I understand this is rather vague (minus the code), but I'm looking more for a start point, or anyone that's run into the same kinds of issues. The bullet point scenario is as follows:
Parent view already instantiated in existing region.
Clicking on cell in parent view instantiates (navigates to) child view in popup region.
Same click operation needs to pass an object from the parent view to the child view so that the child view can filter its own data based on that object.
Operations are constructed using Prism/MVVM.
Any help, suggestions, pointers, ideas would be awesome.
We had the same scenario and ended up with creating a UiService that are injected to our ViewModels. Our ViewModel base class has a SetModel method which the UiService calls when navigating, for sending parameters to the destination view.
By example:
Clicking a button in the existing View.
Source ViewModel calls UiService ShowView(data).
UiService calls RequestNavigate for the requested view.
UiService calls SetModel on the destination ViewModel (by accessing the DataContext of the requested view) to pass in the data from the source ViewModel.
Depending what you want to pass it can be pretty simple with INavigationAware
Sounds like you want to pass something like query string - parameters, etc. Code to open window will be like this:
var query = new UriQuery
{
{ "MailItemKey", this.SelectedMailItem.MailItemKey.ToString(CultureInfo.InvariantCulture) }
};
RegionManager.RequestNavigate(RegionNames.Popup, typeof(MailItemView).Name + query.ToString());
And inside MailItemViewModel which is our popup's VM code is like this:
public override void OnNavigatedTo(NavigationContext navigationContext)
{
var mailItemKey = int.Parse(navigationContext.Parameters["MailItemKey"]);
}
If you want to pass custom objects - it will be more complex. I would look for MVVM in the box samples - there is some code on how it's done. I had to re-work it whole lot and code is not really copy-pasteable.
Sounds like a perfect use of a RegionContext.
Parent view contains a region that can have multiple "child" views activated in it. They need to share some context or data. Set a region context and bind or pass whatever info all the "child" views in the Region will need.
See the Prism samples around RegionContext.

Using PhoneApplicationPage as a nested view container

In MVVM Light toolkit for Windows Phone, whenever I am to add a new MvvmLightView (WP) item, I end up with the template creating a PhoneApplicationPage for me.
What about cases, when I want to create a nested view, for example in case of a ListBox ItemTemplate view.
Before MVVM Light, every time I needed a view to separate markup to, I would have created a standard UserControl and that worked fine.
Should I only use MvvmLightView whenever creating a navigable pages?
The item template is a guidance, that produces some code for you. It is not, nor does it intend to be, the single way of creating views or sub views.
In the case you are mentioning, it is usual to create a user control hat is backed on its own view model. This sub-view view model is then included as a property in your main view model. To pass it to your sub-view (e.g. a user control) you bind this property to the user control's DataContext.
<ext:MyUserControl DataContext="{Binding MySubViewProperty}"/>
However, you do not need a separate view model, in some cases it is more appropriate to share the main view model. In this case you do not need to do the above binding, as it is do one implicitly. Also, when you are using the user control within an DataTemplate the templates DataContext is passed to the user control implicitly and you do not need the binding. In general you only need to set the data context when you want to bind to a property of the current context, or to another context.
MVVM is about freedom and MVVM Light about supporting the developer in using this freedom. All guidance are best practises and provide usually the easiest an/or most consistant way, but nothing stops you going down another route for a good reason. Especially the templates are just shortcuts that provide for one problem, but not for the general (meaning every) case.

Switching between NSViewControllers

I'm developing a Mac Application. The application has a common source view on the left and a detail view on the right which is the main part of the whole window.
It's like a Master-Detail relationship, but each element in the source view require another detail view. In fact, I have designed a specific NSViewController for each element in the source view.
If I'm switching between these NSViewControllers, that means If I select another element in the source view, I remove the current view and add the view of the newly selected NSViewController. Everytime I change the NSViewController, its state will be lost. When the user comes back to that NSViewController, he has to start over.
My question now is: How can I save the state of the NSViewController, so that I can switch between these without losing its states and can continue where I have left?
Two considerations about your problem:
Keep model data in model classes. This means that you can always recreate a view controller and set its represented object provided the model classes have kept the changes made via the view controller. When you need to instantiate a view controller, set its represented object to (a representation of) a model class.
When removing a view from its superview, you do not necessarily need to release its corresponding view controller. Instead, you can keep strong references to all view controllers in your window controller/application delegate, so no state is actually lost.
Use NSArchiver. Implement archiving/unarchiving in your dealloc/init methods and store each view controller's state in a file named after the class (if you have one item per view controller policy). Otherwise think of some simple naming convention and use it.

Resources