Creating multiple instances of a viewmodel in Prism/Silverlight - silverlight

I have a prism/silverlight view and it is mapped to a tabitem in a tab control of my shell.
It looks like this.
<sdk:TabControl>
<sdk:TabItem Header="User Portfolio" Regions:RegionManager.RegionName="MainRegion" />
<sdk:TabItem Header="Benchmark Portfolio" Regions:RegionManager.RegionName="BenchRegion" />
</sdk:TabControl>
The view consists of a datagrid,textbox and a button such that the datagrid maps to an observablecollection in the viewmodel and when the button is clicked, the text in the textbox gets added to the datagrid(and the corresponding collection).
Now, I want to declare multiple instances of this view-viewmodel pair. That is, in tabitem "MainRegion" I want one instance. In tabitem "BenchRegion" I want another instance
How do I do this?

You need to get the container, and for each instance of the view model you need to use IUnityContainer.ResolveType<>() to initialize the instance (Make sure you register your types first IUnityContainer.RegisterType<>()). You can think of ResolveType<>() as Prism's form of a constructor. Then for the each view you need to set the datacontext to your initialized view model for that view.
Edit I should note that this is for Prism 2.0 I know that with Prism 4.0 there are alternatives to unity.

Related

Use properties of the base control that is inside the UserControl

How can I use the properties of the controls that are inside a user control without having to use DependencyProperty?
Since, if for example I want to use all the properties of a button, I would have to declare all these?
And if there is another way without user control and it is the correct one, I would appreciate it if you answered it. (Google translator, sorry)
UserControl:
<UserControl x:Class="UserControls.UserControl01"
...
>
<Grid>
<Button x:Name="uc_btn" />
<TextBox x:Name="uc_txt" />
<DataGrid x:Name="uc_dtg" />
</Grid>
</UserControl>
Code using the UserControl:
<Window x:Class="UserControls.wnd02"
...
>
<Grid>
<local:UserControl01 uc_btn.Background="Red" uc_txt.Margin="10" uc_dtg.BorderThickness="5" Margin="90" />
<local:UserControl01 uc_btn.Background="Green" uc_txt.Margin="25" uc_dtg.BorderThickness="20" Margin="5" />
</Grid>
</Window>
It is not usual to do what you are asking.
Let's consider a usercontrol which is intended to work as if it is one single control. For example a time picker. This contains two sliders which increase/decrease hour and minute. You can also overtype in the hour and minute textboxes and there's a : between the two textboxes.
This usercontrol is all about the one property though. Time. You don't care what the minutes background is externally. If this changes it's internal to the usercontrol.
In this scenario you'd usually add a TimeSpan dependency property to the usercontrol and this is the only thing anything external to it uses.
Pretty much all commercial WPF development uses the MVVM pattern and that TimeSpan would be bound to a property in the parent view's viewmodel.
That's one scenario.
Another is where a usercontrol encapsulates a bunch of UI which is then re-usable.
Styling has scope so when you apply a style to say a Button in a window then that would apply to any Buttons in a usercontrol within it. Setting their properties.
There are also certain dependency properties marked as "inherits" whose values propogate down the visual tree.
One such is DataContext and it is this which most teams would use to deal with properties within a usercontrol.
Using MVVM there would be a MainWindowViewModel.
That would have (say ) a ChildUserControlViewModel property. That would be associated with usercontrol using a datatemplate specified datatype.
You'd then bind properties of whatever is in a usercontrol to properties of ChildUserControlViewModel or properties of MainWindowViewModel using RelativeSource binding.
ViewModel first is a common navigation and composition pattern for WPF. You should be able to find numerous blogs explain it better than I can in a SO post.
Here's one:
https://social.technet.microsoft.com/wiki/contents/articles/30898.simple-navigation-technique-in-wpf-using-mvvm.aspx

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.

When creating VMs for UserControls, who should create and set the VM?

I'm getting a little confused about how to layout my code in MVVM - if I have a UserControl with a corresponding VM class, how should other controls consume my UserControl?
Should consumers bind directly to the VM or should I duplicate only a subset of these properties I want to actually be used as DependencyProperties of the UserControl?
For that matter, should the UserControl's VM be injected into the UserControl's code-behind or should the VM of any control that uses this UserControl contain it as a dependency and bind it to the UserControl instead?
Just to make it clear: Suppose I have a ListBox in a UserControl and use it in a Window that is already implemented with MVVM. But I'm confused about the implementation of the UserControl VM and the corresponding bindings.
I would think the ideal solution would be to expose the SelectedItems of the ListBox via dependency properties in the UserControl, and then the Window which uses the UserControl would bind to these.
Or should the Window's VM have a reference to the VM as a property, have it injected and bind directly to the properties on that instead?
Should dependency properties only be defined in UserControls or can / should they be defined in the VM?
I'm thinking the Window would bind, from within the XAML of the Window, either via
{Binding ElementName=myUserControl, Path=SelectedItems}
or
{Binding Path=MyViewModel.SelectedItems}
It just seems to make more sense to do it via the former, since the latter requires that the View knows about another VM?
> how should other controls consume my UserControl?
Via exposed dependancy properties on the usercontrol only.
>Should consumers bind directly to the VM or should I duplicate only a subset of these properties I want to actually be used as DependencyProperties of the UserControl?
Each control should be a stand alone entity, there shouldn't be any secret handshake (either to or from) to use the control. Think of the design like you are Microsoft and many different users will use your controls. So answer #1 is just as relevant; think a stand alone entity.
>I would think the ideal solution would be to expose the SelectedItems of the ListBox via dependency properties in the UserControl, and then the Window which uses the UserControl would bind to these.
The window which hosts your controls will have a View Model which contains a Observable list of data items. That will hold the data which the user control(s) will bind via their dependency properties. THink of it as a producer pattern with many consumers. The consumers are the controls. Whether the controls have VMs or not is immaterial to the running of the main program; for each control is its own island.
Keep in mind when working with WPF and MVVM that your View layer is merely a user-friendly way of drawing your Models and ViewModels, and that your View is not actually your application. Your View actually has to know the basics about your data layer so it can define how to draw it.
So if your application needs to display a list of Items and maintain a SelectedItem, than that should be in your ViewModel or Model somewhere, not in the actual View layer.
Typically for me UserControls are one of two things:
Either a standalone UserControl that can be used anywhere without a specific DataContext, and that expose DependencyProperties for any control-specific values. Examples are things like a Calendar control or a Popup control
<local:MyUserControl Items="{Binding SomeItemList}"
SelectedItem="{Binding SomeItem}" />
Or they are a UserControl that is meant to be used with a specific ViewModel only. This is far more common for me. The ViewModel is a property somewhere in the data layer, and I usually have an implicit DataTemplate in the application somewhere to tell WPF to use that UserControl anytime it needs to render that specific ViewModel
<DataTemplate DataType="{x:Type local:SomeViewModel}">
<local:MyUserControl />
</DataTemplate>
<ContentPresenter Content="{Binding SomeViewModelProperty}" />
Also, at no time should you set the DataContext of a UserControl from inside the UserControl itself, because the UI layer is only meant to be a UI representation of your data layer (your Models/ViewModels), and by setting the data layer from inside the UserControl you are making it so that the UserControl cannot be used to draw any other data object.

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

WPF DataTemplate and usercontrol lifetime

I have a tab control with a few tabs. When a tab is selected, I set the content of the tab to its corresponding view model.
I also have a DataTemplate defined for the base view model that all of the other view models derive from:
<DataTemplate DataType="{x:Type vm:BaseViewModel}">
<view:BaseView/>
</DataTemplate>
This way, my view models, which are nearly identical, will be displayed using the same base view.
BaseView is a user control. In BaseView I have an Infragistics XamDataGrid defined. It seems that only one instance of this grid is created for all of the view models, meaning I can switch between tabs as many times as I want but the user control is never recreated from scratch.
How does WPF handle the lifetime of user controls when combined with DataTemplates?
The problem I am trying to solve is that in the xaml of BaseView, I have defined a Field in the XamDataGrid like so:
<igDP:XamDataGrid.FieldLayouts>
<igDP:FieldLayout>
<igDP:FieldLayout.FieldSettings>
<igDP:FieldSettings DataValueChangedNotificationsActive="true"
AllowCellVirtualization="False"
AllowResize="True"
AllowRecordFiltering="True"/>
</igDP:FieldLayout.FieldSettings>
<igDP:Field Name="IsDirty" Visibility="Collapsed"/>
</igDP:FieldLayout>
</igDP:XamDataGrid.FieldLayouts>
The IsDirty column (all of the view models have an IsDirty property) is only correctly collapsed the first time the grid is displayed. When I click another tab, the grid's data source changes, a new FieldLayout is created by the grid, and it doesn't pick up the Collapsed setting for IsDirty. As a result the IsDirty column is visible. My thinking was if I can force the user control to be totally recreated, I could avoid this issue.
Add DataTemplate to Resources and set x:Shared="false"

Resources