Use locator to manage multiple view-viewmodel pairs in Panorama Page - wcf

I'm new to Silverlight/MVVM. I tried some example of MVVM Light, it looks great.
For my scenario, I want to create a Panorama Page, for each Panorama Item, showing my usercontrol, a item list for a customer.
I've built usercontrol(view), viewmodel and WCF service model and works well in a single Panorama Item(Only use first customer).
Also, I use Locator of MVVM Light shown in MIX10 demo, it enables me to make design time data for Expression Blend.
My viewmodel will receive a parameter of customer ID then exchange data with WCF based on this ID.
And the customer list also comes from WCF. So I can't actually makes viewmodels in Locator's static constructor.
If viewmodels are built in runtime by calling Locator, how to make data binding?
The only way I think about is to make viewmodel object in usercontrol's constructor and make it datacontext.
Is there a better solution?

If you want to keep the same declarative model in the XAML, you can put a CurrentCustomerViewModel property on the locator and then set property to the right viewmodel before you navigate to the page.
Personally though for pages like that I typically put a viewmodel factory method on the locator (so it can cache them, etc) and call it from the OnNavigatedTo method, something like this.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
string id = NavigationContext.QueryString["customerID"];
vm = ViewModelLocator.GetCustomerViewModel(id);
DataContext = vm;
base.OnNavigatedTo(e);
}
Then I just use Blend's sample data capabilities for design time data. This way also helps support pinning the page to the start screen since that will be the entry point to the app and I won't necessarily get a good chance to set the "CurrentCustomerVM" property anyway.

Related

How to use DI with WinRT

In a WinRT Page how can I inject dependencies?
I am thinking of doing something like this:
/// <summary>
/// A page that displays an overview of a single group, including a preview of the items
/// within the group.
/// </summary>
public sealed partial class MyPage : NSyncApplication.WinRT.Common.LayoutAwarePage
{
IMyDependency _myDependency;
public MyPage(IMyDependency myDependency)
{
_myDependency = myDependency;
this.InitializeComponent();
}
.
.
.
}
If this isn't a good practice please explain and recommend an alternative solution.
Note:
I don't need the specific DI containers that can be used with WinRT, that's been answered already and any idiot can look at nuget gallery and pick their choice.
This question is about how I can plug into the Page factory and inject my own dependencies. I have also looked at Prism for WinRT and that thing is even more convoluted than I remember the WPF version to be.
To repeat:
How can I inject into the page directly. Is there a page factory
or something that I can tap into to add custom instantiation code?
Should I inject to the code behind and make it a viewmodel? The Prism MVVM example had
another layer of abstraction for the ViewModel separate from the
code behind (which's considered part of the View). This is nice and cool, but requires more wiring and
custom mark ups than I care to do for my relatively simple project. I am hoping to roll with something more "light-weight". But may be there's an argument to be made against that, please explain.
Please, check MVVM-Light. They use VMLocator which exposes view models to which XAML can bind. On MSDN Magazine you can find an example of how to use it.

MVVM - Summary/Detail

So I'm trying to wrap my head around MVVM and I'm finding that I have more questions than answers. The tutorials don't go far enough for me when it comes to the next step...
Basically I want a list of items and then a way to get the detail of each item.
Below is the examples that I've found online and they work great for displaying the list, but I need to know how I can use my VM to get the detail of this item.
private IList<item> m_items;
private IList<item> m_Item;
private IList<item> getItemDetail(Int32 iId)
{
var myItem =
from i in items
where i.iId == iId
select i;
m_Item = new List<item>();
foreach (var item in myItem)
{
m_Item.Add(item);
}
return m_Item;
}
public myViewModel()
{
m_items = new List<item>
{
new item(1, "test,),
new item(2, "test2"),
new item(3, "test1")
};
m_Item = new List<item>();
m_Item = getItemDetail(iId);
}
Update:
I updated my View Model code above. I think what I've done is I have added another List where when the user navigates to a detail page the view model gets called with the specific ID which then populates the detail List. I probably don't need a list here but I wanted to try to keep it consistent with the main page code.
In my detail page I'm setting up the VM this way:
itemViewModel VM = new itemViewModel((Int32)navigationParameter);
DataContext = VM;
When I break on the VM variable I see my 2 lists. However, my binding doesn't work on the XAML. If I need to post some sample XAML let me know. I can do that but I'm hoping there is something I'm missing here.
I'm trying to learn MVVM and I want to do things right. So instead of continuing down a wrong path I would really like to know the "right" way of doing things. So if you see errors, please let me know.
Thanks!
right, i'd suggest you go back to basics first and watch Laurent's Mix sessions about MVVM, you find links to then from the mvvmlight site on codeplex.
but to break it down you've hit a few of the hurdles I did when I first started.
1: (the biggest gotcha) for databinding to work, you must expose data using a property (get and set pattern), just a list variable won't work. this goes for everything you want to bind to. The alternative is to set item sources directly in code but you will loose all the features of databinding, including updates.
2: to understand databinding you need to understand the INotifyProperty changed pattern, this is the underlying gubbins (technical term ;-D) to enable binding to work properly. as suggested start a new "master/details" project template and walk through it, from the viewmodels holding the data to the views (pages) looking at the data in the view model
3: use observablecollections for lists, they are just better for binding and are basically just lists with extras
4: remember you can also bind the "selecteditem" or "selectedindex" of a listbox to capture what the user has selected, just be sure to set the binding to "twoway" so the view can push data to the viewmodel and not just read, like this: {binding myselecteditem, mode="twoway"}
hope this helps but if your still stuck Laurents videos are the best, just watch them a few times and follow what he does line by line
I believe you want to use what Microsoft calls the "master-detail binding scenario", where several controls bind to a single collection or to its selected item. To do so, you need to bind to a so called collection view, which is just a layer on top of the collection used by WPF. For instance, you can bind a ListBox's ItemSource and a ContentControl's Content to the same collection view, and the ContentControl will display the details of the the ListBox's selected item.
see: http://msdn.microsoft.com/en-us/library/ms752347.aspx#master_detail_scenario
P.S. you may want to use an ObservableCollection instead of a List, and make sure your view model implements INotifyPropertyChanged.

Dynamically changing the ViewModel of a View in an MVVM, MEF implementation

I have a usercontrol that i want to use throughout my Silverlight MEF MVVM solution.
I want to be able to link it up with one of a number of ViewModels depending on which module i am in. What this control does is list the records of a given entity so i can Add, Edit or Delete. I realized i would be using this control in multiple locations - to update several lookup tables, so i decided to make it's ViewModel dynamic. As seen below, I am using the Galasoft MVVM plugin.
if (!GalaSoft.MvvmLight.ViewModelBase.IsInDesignModeStatic)
{
// set DataContext
DataContext = PluginCatalogService.Instance.FindSharedPlugin(ViewModelTypes.ViewModelMT, PluginType.ViewModel);
_viewModel = (ViewModelMT)DataContext;
}
My question is how can i dynamically change from ViewModelMT to ViewModelCT to allow me to independently display lookup tables e.g. Maintenance Types and Contract Types on an instance of this same usercontrol? I took a look at the Viewmodel locator, but I'm still not sure how to get this done.
Thank you
I don't think this is really a ViewModel thing. It's more of a Service problem.
Your ViewModel for the control will not change but you'll dynamically slot in the required service to maintain your list. ie. MaintenanceTypeService and ContractTypesService will implement IListMaintenanceService which exposes an list of items and Add,Delete and Edit commands.

ShowDialog a RadWindow with MVVMLight

I have a functional MVVM patterned SL app with a RadWindow (essentially a ChildWindow), that I would like to remove the code-behind in my view that shows the window using its ShowDialog. Both the main view and the window is bound to the same ViewModel if that helps.
The button has both a ViewModel command using a MVVMLight RelayCommand to handle setting state as well as the event handler in the View.
The ultimate solution/pattern will be reused 20+ times so something better than code-behind would be great.
Thoughts?
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var window = new RadWindowTest.Controls.ChildWindow1();
window.Closed += new System.EventHandler<Telerik.Windows.Controls.WindowClosedEventArgs>(window_Closed);
window.ShowDialog();
}
In this case I would suggest you implement DialogService. This service you can inject into your view model, for testing you will have to inject an instance that does not depend on the view, thus maintaining testability. You can use the ViewModelLocator to make this service available to your application.
Another approach would be to implement a ViewBase class that implements an interface that allows you to display the dialog. This interface is now used by the ViewModel to display a dialog. Again to test you need to provide a different implementation of the interface. A sample can be found here.
Both ideas revolve around the same concept of factoring out the function that shows the dialog. In order to strictly de-couple the View and the ViewModel you will have to think about how the ViewModel specifies which dialog has to be shoen, and how the dialog resut or dialog model is returned to the calling ViewModel.
Which approach is better is open to your judgement. Personally I prefer the first approach as I do not have to inherit the views from a common base class.
PS: Use a command to get to the point in your ViewModel where you want to show the dialog. Using a dialog service should need no code behind.

Why to avoid the codebehind in WPF MVVM pattern?

At the article, WPF Apps With The Model-View-ViewModel Design Pattern, the author who is Josh Smith said:
(1) In a well-designed MVVM architecture, the codebehind for most Views should be empty, or, at most, only contain code that manipulates the controls and resources contained within that view. (2) Sometimes it is also necessary to write code in a View's codebehind that interacts with a ViewModel object, such as hooking an event or calling a method that would otherwise be very difficult to invoke from the ViewModel itself.
My question is ,at the (1), why the empty codebehind is regarded as a a well-designed MVVM.(It sounds that the empty codebehind is always good.)
EDIT: My question is, as the following, why the approach like the AttachedCommandBehavior or the InvokeCommandAction is tried to avoid the codebehind coding.
Let me explain more detail.
As far as the (1) is concerned, I would think like the following situation as from the AttachedCommandBehavior. As the Border doesn't implement the ICommandSource for the MouseRightButtonDown, you cannot commonly bind the event and the ICommand, but can do with the AttachedCommandBehavior.
<!-- I modified some code from the AttachedCommandBehavior to show more simply -->
<Border>
<local:CommandBehaviorCollection.Behaviors>
<local:BehaviorBinding Event="MouseRightButtonDown"
Command="{Binding SomeCommand}"
CommandParameter="A Command on MouseRightButtonDown"/>
</local:CommandBehaviorCollection.Behaviors>
</Border>
OR
We can do this with the System.Windows.Interactivity.InvokeCommandAction.
<Border xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseRightButtonDown">
<i:InvokeCommandAction Command="{Binding SomeCommand}"
CommandParameter="A Command on MouseRightButtonDown"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Border>
BUT,
We use the following XAML and its codebehind having the Border_MouseRightButtonDown method, which is linked to the (2) Josh Simth said above.
<Border MouseRightButtonDown ="Border_MouseRightButtonDown"/>
I think using the codebehind as above is not bad just because the difference between these is only where binding a command or add event handler is.
What do you think about this?
why the empty codebehind is regarded as a a well-designed MVVM
Having a code-behind file which consists solely of a call to InitializeComponent() in its constructor means you have achieved purity - you have absolutely zero logic in your codebehind. You have not polluted your view with any code that rightfully belongs in the viewmodel or model. This means a couple of things:
the viewmodel (and model) is easier to test in isolation
you have achieved a good level of loose coupling, which has excellent benefits from a maintenance and extensibility perspective
The benefits really become noticeable when you have to change your UI, i.e. you switch from using a ListView to a DataGrid, or you change from using the standard Microsoft controls to using some other vendor's.
As mentioned though, it is sometimes impossible to avoid a little code in the code-behind file. What you should ensure is that the code you do have is purely UI related. As an example, if you have ComboA and ComboB, and ComboB is set in response to the selection in ComboA, then setting the SelectedIndex of ComboB from the view is fine, but setting the Items or the SelectedItem of ComboB is not - those properties are both data related and should be specified via binding to the viewmodel. The SelectedIndex property is directly visual related and somewhat independent of the actual data (and it is irrelevant to the viewmodel).
If you do access the viewmodel from code-behind in the view, you should try and do it via an interface. This means your viewmodel is injected or given to the view as an interface. (Note that the binding subsystem doesn't know or care about the interface, it will continue to bind in its normal way. What this achieves is better code, with less tight coupling). The way I code it, the viewmodel has no idea that a view exists, and the view only knows about the viewmodel as an interface.
One thing to remember though is that MVVM is a pattern, and a pattern is simply a recipe or prescription for achieving a certain result in a certain situation. It shouldn't be treated as a religion, where non-believers or non-conformers are going to go to some purgatory (although adherence to the pattern is good if you want to avoid the purgatory of maintenance hell and code smell).
If you want an excellent example of how this particular pattern helps, try writing a few reasonably complicated screens in ASP.Net, and then write the same in WPF or Silverlight, and note the difference.
Edit:
let me answer some of your questions, I hope it helps....
the viewmodel's (model of view) role , in my view, has UI logic and state of a view
The viewmodel should never have any UI logic or "view state" in it. For the purposes of this explanation, I would define view state as scroll position, selected row index, selected index, window size, etc. None of those belong in the viewmodel; things like SelectedIndex are specific to the way the data is shown in the UI (if you change the sort order of a DataGrid then the SelectedIndex can change, even though the SelectedItem is still the same). In this particular case, the SelectedItem can be bound to the viewmodel, but the SelectedIndex shouldn't.
If you need to keep track of UI session type info them then you should come up with something generic (for example, I have persisted view state before by saving important stuff into a KeyValuePair list) which is then "saved" with a call to the viewmodel (via the interface I mentioned previously). The view has no idea how the data is being saved, and the viewmodel has no idea the data is coming from a view (it has simply exposed a call through its interface).
and the view's role is displaying some contents and synchronizing the viewmodel(having databinding code)
Yes, the view's responsibility is simply to visually display data presented by the viewmodel. The viewmodel gets the data from the model (the model is responsible for making database calls or WCF webservice calls, this will usually be done via a "service", but that is a whole other discussion). The viewmodel can then shape or manipulate the data, i.e. it may get a list of all customers, but only expose a filtered version of that list (maybe the current customers) in a public property which the view can then bind to.
If the data is to be manipulated into something visual (a common example is an enum value being translated into a color), then the viewmodel still only has the enum value(s), and the view still binds to that value, but the view also uses a converter to translate the pure data to a visual representation. By using the converter the viewmodel has still avoided doing anything UI related, and the view has avoided any real logic.
The MVVM can split code and page design completely; coders just care about coding and designers only care about design. But:
I've never seen any designer who using Blend or understanding XAML.
Almost all XAMLs are written by coder himself.
There is nothing inherently bad in code-behind. For simple cases, it's fine to have it. However, UI logic can get difficult to manage in many scenarios. Encapsulating that logic in attached behaviors and view models allows us to isolate the variables (and test them) so that it's easier to comprehend and maintain.
If testability is a concern, the more of your UI logic that you can encapsulate in viewmodels and attached behaviors, the more you you will be able to verify without resorting to UI testing. (While it doesn't eliminate the need for UI Testing altogether, it does provide a first level of verification before engaging in UI Testing which will be more time/resource intensive.
I think the quoted section refers to the way data is visualized. I think they mean you should not write code in code behind that is, for example, related to how or where the data is displayed (for example something like: label1.Text = ...). Doing things like that using bindings makes it easier to separate design and code (what happens if you need the data to be displayed in a text box named "tbTest" in a later version? You'd have to change your code behind).
They are not saying that you shouldn't have any code in code behind - they are just saying that in an ideal world, you'd only react to events or process data that could not otherwise be processed.
At least that's what I understand from the section you quoted.
The MVVM pattern is powerful but I find it too 'Purist'. I can see benefit is having the code behind handle all the commands and properties in the view while the ViewModel is concerned with any translation to business model properties.
A benefit of this is that if you wish to change the user UI, perhaps from desktop to browser it is likely to be just replacing the View and its code behind.
Just my thoughts!!