Note: this is a different question to the one here: Pass dependency property to child view
I am currently creating a usercontrol in wpf which consists of several 'screens' that the user will click through.
For each 'screen' I have created a view with it's own viewmodel (e.g. View1.xaml, View2.xaml). The main usercontrol can then access these views:
<UserControl.Resources>
<local:ModuleBaseViewModel x:Key="ViewModelDataSource" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource ViewModelDataSource}}">
<local:View1 Visibility="Visible"/>
<local:View2 Visibility="Hidden"/>
</Grid>
I would like to pass a button click from a view back down to the parent usercontrol so that I can hide that view and show the next one. Can someone explain to me how to do this?
Thanks!
If you are using MVVM and WPF, chances are you are using an IoC container. Almost every IoC container contains a method of publishing an event and then subscribing to that event. In Prism, the code looks something like this:
EventAggregator.GetEvent<SomeEvent>().Publish(ParametersHere)
I would suggest you look at your options for publishing events and reacting to them. Then your parent view model can respond to the children's events.
Related
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
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.
I'm using an MVVM pattern for my WPF application. If the "home" view model, which controls the layout of my application's main window, I have a ChildViewModel property. This holds a viewmodel that can be switched according to what the user is doing. When they select menu items, the child view model switches and the main area of the screen (it's in an Outlook style) switches accordingly.
I do this with a ContentControl and DataTemplate like this: (I'm only showing one of the embeddable views here to keep it short).
<ContentControl Grid.Row="1" Grid.Column="1" Margin="3"
Content="{Binding ChildViewModel}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:VersionsViewModel}">
<Embeddable:VersionsView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
I also want to add a ribbon to my main window, using the Telerik RadRibbonView control. I want this to have some fixed tabs and buttons that are always visible. In addition, I want to add and remove entire tabs, and buttons within existing tabs, according to the type of child view model. I'd like this to be done in the view in a similar manner to the way I've done the content control, above.
Is this possible? I've tried lots of things but got nowhere so far. I know I could do it by creating a huge "super ribbon" and binding visibility properties but this seems cludgey. I could also have multiple ribbons, each containing the common controls, but this would cause a maintenance problem.
In the end I went with the "super ribbon" approach, as I couldn't find any other way.
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).
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.