Silverlight MVVM question regarding views and viewmodels - silverlight

I feel mysefl confused about how to implement view switching when view model changes. Example of what i'm tring to do:
The control I want to make is something like a wizard control. I have a list of view models added to collection of wizardsteps, and a current item viewmodel. How to display the view of active view model and switch them then active view model changes? How do I bind them?
In WPF I'd use DataTemplate but Silverlight doesn't support x:Type.
<DataTemplate DataType="{x:Type ViewModel1}">
<view:View1 />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel2}">
<view:View2 />
</DataTemplate>

I think a wizard is a case where you should have one ViewModel for multiple Views.
You could control the visibility of each view with Properties (IsPage1Visible, IsPage2Visible,...), Commands (PreviowsPageCommand, NextPageCommand, CancelComamnd) and all logic in only one VM.
Put all "pages" of the wizard in one UserControl and bind the visilitiy of each with the boolean properties and a BooleanToVisibilityConverter.

Check this out, it talks about non-linear navigation in SL/WPF and how to maintain state. http://karlshifflett.wordpress.com/2010/07/07/non-linear-navigation-in-silverlight-4/

Related

WPF multiple views [duplicate]

I am working on a an WPF MVVM application where I need to have a Main Window with just a logo and it has to show child views inside it. I don't have any controls in Main Window all the controls reside in child view for example Buttons like Next, Back, Cancel and some text blocks etc. Now If users select Next button on the child view I have to draw or load the next child view inside the Main Window. If Back button is clicked I have to go back to the previous child view. So basically I am changing the child views depending on which button is clicked. Also I am maintaining different view models for every child view. Now the problem is I am not able to figure how should I link the child views to there respective view models. This application is similar to some Installation applications where different dialogs are shown depending on the selection and the button clicked by the user.I am new to this wpf and don't want to use MVVM Light , Prism etc. Any detailed help will be greatly appreciated. Thanks in advance.
One of the easiest ways to associate any data type with XAML controls is to use a DataTemplate. Therefore, you can simply add something like this into your Application.Resources and as long as you do not set the x:Key properties on the DataTemplates, then they will be explicitly applied by the Framework whenever it comes across instances of your view models:
<DataTemplate DataType="{x:Type ViewModels:HomeViewModel}">
<Views:HomeView />
</DataTemplate>
...
<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
<Views:MainView />
</DataTemplate>
Then displaying the view is as simple as this:
<ContentControl Content="{Binding YourViewModelProperty"} />
In code behind, or your view model:
YourViewModelProperty = new MainViewModel();
It's often handy to create a base class for your view models and then the YourViewModelProperty can of that type and you will be able to interchange them using the same property and ContentControl.
UPDATE >>>
The general idea is that you have one MainViewModel class with one BaseViewModel property data bound to one ContentControl in MainWindow.xaml... the navigation controls should also be in MainWindow.xaml and not in the views themselves. In this way, the MainViewModel class is responsible for changing the property to the relevant view model instances when it receives navigation Commands from the MainWindow.xaml.

How to access properties of a UserControl

I have an application that uses Caliburn.Micro. My View contains a user control which contains e.g. a tab control. I want to be able to access that tab control from the outer ViewModel to select a particular tab. Is it possible?
Thanks.
The standard MVVM way is to have the TabControls SelectedItem property bound to a property on your viewModel.
<TabControl ItemsSource="{Binding PropertyToYourViews}"
SelectedItem="{Binding PropertyToYourSelectedView}">
</TabControl>
If you do it this way your ViewModel does not have to know about the existence of the TabControl.
The next step is dependant on your implementation. Your outer ViewModel could simply keep a reference to the child viewModels SelectedView property and access it directly however,
If you want to keep your ViewModels decoupled then you will need to implement some sort of notification system. I'm not sure of the specifics of Caliburn.Micro but most MVVM frameworks offer some kind of solution for this.
Implementation would depend on exactly how you have it set up, but you can bind a variable in your view model to the SelectedItem of the TabControl

How do I navigate from a ViewModel?

I am writing a small contrived WPF application for a university project, and i'm taking the opportunity to learn the MVVM pattern. I've implemented my initial start up window which will be a login page.
I have bound the login button to a command that I have derived from ICommand, which is injected with the LoginViewModel. The LoginViewModel then validates the customer through a WCF service I have created.
My question is, once the viewmodel receives notification that the validation is correct, how should I navigate to the next page/window from the viewmodel? I don't want to create an instance of a new window within the viewmodel. Should I be using pages here instead? I'm keen to understand the best practices from the start, I don't want to be wasting my time learning the bad ways of doing this.
Thanks.
Instead of changing views, you can change viewmodels and use a ContentControl to bind the viewmodels to specific views: create a main view on top of the other views which will manage the view changes via commands (in this example set the CurrentViewModel from your command handler):
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:LoginViewModel}">
<local:LoginView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:FirstPageViewModel}">
<local:FirstPageView/>
</DataTemplate>
</UserControl.Resources>
<ContentControl Content="{Binding Path=CurrentViewModel}" />
This way you don't need to mix up the Views and ViewModels, you're not creating views from the VMs. Actually in my case it was the child page which requested the view change with an event.
I've not done pages, but for your login screen I would have my LoginViewModel expose a LoggedInEvent.
You can then have a parent ViewModel create the LoginViewModel and destroy it again when the LoggedInEvent is raised (and create whatever new views you need).

MVVM - WPF Desktop

Just started learning MVVM. I have a tabcontrol where I am adding multiple instances of same views/pages
Dim tb As New UXTabItem
tb.Header = "Childrens"
tb.Name = "tab" & itrt
itrt = itrt + 1
tb.Source = New Uri("/Views/childrens.xaml", UriKind.Relative)
UXTabControl1.Items.Add(tb)
Since each of the same view will handle different data but since the uri is same so all the tabs get populated with same view and changes reflect on each tabs. Which should not be the case. Should I be using a separate viewmodel for each of those? Any example would be much helpful.
One of the primary goals/advantages of MVVM is that you don't create WPF UI objects in code.
You should be populating a collection of view model objects and binding the ItemsSource of the TabControl that you define in XAML to it. You should have a DataTemplate defined for the data type of those objects and put their XAML in there, instead of loading it at runtime.
The TabControl is a little tricky, because it uses two templates: the ItemTemplate is used to define the look of the tab, and the ContentTemplate is used to define the look of the tab items' content. It's pretty common to see this:
<TabControl ItemsSource="{Binding MyItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
which populates the tab with a Text property on the view model, and the tab item's content with whatever template in the resource dictionary matches the view model's type.
I would have an ObservableCollection<TabViewModel> Tabs in my parent ViewModel, and bind the TabControl's ItemSource to that. Each Tab has it's own instance of TabViewModel, so adding a new Tab would mean adding a new TabViewModel to the Tabs collection in the ParentViewModel.
The TabViewModel would contain properties for things like Header or Uri, and these would be bound to the UI at the appropriate spots. Each TabViewModel can be drawn using the same View, but the data inside the object would be different for each tab.
My ParentViewModel would also contain a TabIndex property that defines which tab is selected
This is NOT trivial, IMO, and Rachel and Robert are both right.
Think of this task being one of managing 'work spaces", each represented by a tab control. I like to structure my view models into three related layers
DetailViewModel - the model for a given workspace (represented by a tab control)
MasterViewModel - the model for a collection of detail view models (ObservableCollection{DetailViewModel}). You would use this to bind to a list ion our presentation that shows what items may be selected for editing / display in a tab control. This is where filtering of the list would also be handled, if you allow that.
ShellViewModel - the model that actually has a collection of workspaces (ie, ObservableCollection{Workspace} along with the commands to manage them (ie, EditWorkspaceCommand, AddWorkspaceCommand, DeleteWorkspaceCommand). A workspace is a DetailViewModel that has a CloseCommand.
I found Josh Smith's MVVM article on MSDN useful for grokking this design.
HTH,
Berryl

How to create Master Detail view with two user controls in MVVM?

I am little confused about how to create Master Detail view with two different user controls.
There are three choices,
Choice 1
CustomerMasterView + CustomerMasterViewModel
CustomerDetailView + CustomerDetailViewModel
And keep both View Models in App.Resources
But by doing this, binding becomes complex with all static resources source markup code.
Choice 2
CustomerViewModel
CustomerMasterView
CustomerDetailView
Both views share same ViewModel via App.Resources, well even with the binding code has too many items.
Choice 3
CustomerMasterView + CustomerMasterViewModel
CustomerDetailView + CustomerDetailViewModel
Both view's have DataContext set to their corresponding ViewModel. Now here is the little issue,
CustomerMasterView has Selector (ListBox or DataGrid or whatever), whose SelectedItem needs to be bound to CustomerDetailViewModel's "Customer" Property as two way binding.
Does it look good?
<!-- CustomerMasterView -->
<ListBox
ItemsSource="{Binding CustomerList}"
SelectedItem="{Binding DataContext.Customer,ElementName=customerDetailView}"
/>
<local:CustomerDetailView
x:Name="customerDetailView"
/>
But by doing this, I am defying purpose of ViewModel as it adds more dependency in my UI code.
Which one is most preferred way or is there any other way?
Should I create nested View Models?
I am also trying to learn Prism, and I have little confusion of how to do this right, any help will be appriciated.
The simplest appraoch in my opinion would be to have a single view model, with two UserControls.
Your ViewModel would have your list of customers, as well as a "ActiveCustomer" or "SelectedCustomer". Your MasterView (with the DataContext set to you ViewModel), would contain your list, wired up like this:
<ListBox ItemsSource="{Binding Customers}" SelectedItem="{Binding ActiveItem, Mode=TwoWay}" />
Your MasterView will also include your DetailsView (another UserControl). It looks like this:
<views:DetailsUserControl DataContext="{Binding ActiveItem}" />
You might be interested in the BookLibrary sample application of the WPF Application Framework (WAF). It shows how to implement a Master/Detail scenario with two Views (separate UserControls) and two ViewModels.

Resources