I programming a WPF GUI that uses multiple Views. I am using the MVVM Light Toolkit to implement the MVVM pattern.
For Navigating i use this mechanism by changing my main frame to a NavigationWindow and all my views to Pages.
I injected the navigation service in the ViewModel constructor and now I can navigate between the views.
However, i would like to transmit data between the views while navigating. There is a method from Navigation Window that makes this possible through event handlers. I already implemented a method into my Interface but I'm having problems calling the event handler on the navigated View Model.
Can anyone tell me how to call the event handler inside my ViewModel?
Thanks!!
Edit: I tried calling:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
}
But i get an error saying:
OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs)': no
suitable method found to override
I already cleaned my solution and tried a rebuild...
Any ideas?
Edit2:
So i found out that in WPF .Net 4.5 the OnNavigatedTo event is gone. What i couldnt find out why and how i could call something similiar.
I haven't gotten an answer to my question so I will attempt an answer...
Don't over think this...if one needs to transfer information either create a static link to the VM(s) in question, or set aside a static drop on the app class. Either way when a view is shown, subscribe to one of the initialization/load events and pick up the information at the predetermined location.
Related
I am developing an app in which I have used Prism Framework. I have registered viewmodels in bootstrapper as below:
ViewModelLocationProvider.Register<LoginControl, LoginViewModel>();
ViewModelLocationProvider.Register<MainWindow, MainWindowViewModel>();
ViewModelLocationProvider.Register<CountryList, CountryViewModel>();
I have also register prism for Navigation as:
builder.RegisterTypeForNavigation<LoginControl>();
builder.RegisterTypeForNavigation<MainWindow>();
builder.RegisterTypeForNavigation<CountryList>();
Its working perfect but I found that the constructor for each viewmodel is called once while first time navigating to ViewModel. After that same object of viewmodel is served. But I want that after navigation, viewmodel should also dispose and new object is served every time.
I want to achieve some this similar to autofac:
builder.RegisterType<ModuleLoader>().InstancePerDependency()
But I dont found any method in ViewModelLocationProvider to achieve this. Is there any way to achieve this?
Update
Found that when I navigate from one view to another then the view is also not disposed. We I move to same View (Usercontrol in Region) then same object is served which is the real cause for same instance of ViewModel. Is there any way to dispose view after navigation in Prism?
Resolved the issue by implementing IRegionMemberLifetime interface to my usercontrol and adding below property
public bool KeepAlive
{
get
{
return false;
}
}
Right now, I am using Xamarin.Forms PLC project.
I have a label[x] on Page[x], then I will press button and go to Page[xx] ,then I will go back to Page[x] but I need to update Label[x] Text upon some Choices selected on Page[xx].
Which Event should i use to update Label.Text?
I was overriding OnResuem()Function on Xamarin.android, but it is not working on Xamarin.forms, I have no idea which is the best solution.
Some quick solution for this is:
-overriding the OnAppearing() method of the page and change the label.Text property once you change it on the other page
-Change the property to be public and change it on the other page
-Send the property to the next page as a parameter
but what you should do! is bind your property to a ViewModel and use OnPropertyChange() (Xamarin.Forms way and MVVM architecture) Events: a couple of tutorials how to understand this better:
https://blog.xamarin.com/advanced-data-binding-for-ios-android-and-windows/
https://developer.xamarin.com/guides/xamarin-forms/user-interface/xaml-basics/data_bindings_to_mvvm/
https://developer.xamarin.com/guides/xamarin-forms/user-interface/xaml-basics/data_binding_basics/
I'm not sure how youre code works because you havent said. So I'm not sure how Page[x] knows about Page[xx] but it sounds to me like you want to use the OnAppearing() override.
Which from the Xamarin.Forms Page API documentation states:
When overridden, allows application developers to
customize behavior immediately prior to the Page becoming visible.
You could do this by adding the following to your Page[x].xaml.cs file
protected override void OnAppearing()
{
//Your code here
}
I read about "ViewModel to ViewModel navigation" and "View Model Lifecycle" from here:
https://github.com/MvvmCross/MvvmCross/wiki/ViewModel--to-ViewModel-navigation
https://github.com/MvvmCross/MvvmCross/wiki/View-Model-Lifecycle
I can use Init() or Start() methods to initialise current ViewModel.
Also I can pass parameters from one ViewModel to another and receive it in the Init() method.
So my question:
When I created windows phone apps I used "NavigateTo" and "NavigateFrom" methods.
Init() is similar to "NavigateTo".
But I didn't find alternative for "NavigateFrom" method in mvvmcross and I don't know how to reload data when I move 'back' by "Close(this)" or using back button on windows phone.
Could you hint me?
Thanks in advance!
updated
I found out that Messenger (MvvmCross plugin) can help me with informing first ViewModel, when an other second ViewModel has changed data (for example add an item to a collection).
So when the second ViewModel add a new item, first ViewModel reloads the data in the OnCollectionChanged(CollectionChangedMessage obj) method.
Stuart showed how to work with this plugin in the NPlus1DaysOfMvvmCross/N-13-CollectABull-Part2.
Link here: https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/tree/master/N-13-CollectABull-Part2
But I didn't find alternative for "NavigateFrom" method in mvvmcross and I don't know how to reload data when I move 'back' by "Close(this)" or using back button on windows phone.
In general, you don't need to reload data in this event - because the ViewModel is already created and initialised from the previous navigation in the forwards direction.
If you do want to do some refresh of the ViewModel when navigating back, then the IVisible pattern in the N=42 video may help but you'll need to add this to your View and ViewModel yourself - see http://slodge.blogspot.co.uk/2013/11/n42-is-my-viewmodel-visible-can-i-kill.html
I am trying to create a simple onscreen keypad created using buttons (currently a User-control), on those buttons i have a click event, when i click/touch a button i want the value of that button sent to a Text-block in my Main-window.
I can't/don't understand how to make the User-control (keypad) see the Text-block (in Main-window) to add in the value that i need.
I have seen solutions that use command Bindings and solutions that use the visual tree traversing but all of them are the main window accessing the user control, not the other way around.
All the examples are the other way around because that is how a UserControl is supposed to work.
A UserControl is a packaged piece of re-usable functionality. It should not know anything about the code that is using it.
Instead you should expose routed events in your UserControl for things like a when number was selected, and subscribe to them in your main window.
There are many ways to achieve what you want. If your MainWindow.xaml has a UserControl and you want to react to a change from the control in the MainWindow.xaml.cs file, then you could add a delegate to the UserControl code behind and register a handler for it in the MainWindow.xaml.cs file. Implementing new delegates are generally somewhat simpler than implementing RoutedEvents, which is another way that you could handle this situation.
Using a delegate like this will enable you to effectively pass a signal to the main view from the child UserControl code behind, which you can react to in any way you want to. Rather than explain the whole story again here, please see my answers from the Passing parameters between viewmodels and How to call functions in a main view model from other view models? posts here on Stack Overflow for full details on how to achieve this.
So I followed the guide on the following site to restrict the characters a textbox can accept.
http://www.rhyous.com/2010/06/18/how-to-limit-or-prevent-characters-in-a-textbox-in-csharp/
My problem is I can't figure out how to make the event handler trigger in the secondary class. Basically how do I tell VS to look for the event handler code in that class instead of MainWindow? I tried searching, but apparently don't know the correct terms to use. The xaml reference I used was
xmlns:DigitBox="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
Any ideas?
Simplest way I've found to do it is assign the event in your constructor.
public MainWindow()
{
InitializeComponent();
TextBoxCurrency.GotFocus += expandedTextBoxEvents.TextBoxCurrencyGotFocus;
TextBoxCurrency.LostFocus += expandedTextBoxEvents.TextBoxCurrencyLostFocus;
}
I've searched a way to do it in XAML and I did not found an easy and clean way to do it.
You are much better off using commands and command bindings. I'm not sure what the specific command that would would bind to for a text box for your desired functionality, but one of the goals for WPF was to lessen the use of Event Handlers in code behind.
Check out this article for an overview of commands and this article for a way to hook up commands with events. WPF commanding is one of the coolest features to enable true separation of concerns between UI and business logic.
As a worst case scenario solution, you could create your own text box that inherits from the text box control and hook up the events in that class. Your control would then be reusable.