How to reset a viewmodel in mvvm - wpf

How can I reset my viewmodel when the user clicks new button on the view that has the viewmodel as it's datacontext?
For example:
If I have a view NewCustomer and upon save, the data is saved to the DB and the newly created account number is displayed. But when the user clicks the New button in the screen, I want the view (viewmodel) to be reinitialized. Or if the user clicked cancel in the screen to clear all changes.
How can I achieve this? I am using Prism 5.0 and Unity as my container.
If I used IRegionMemberLifetime, I can clear the viewmodel data when I navigate away and navigate again to the view (by setting the KeepAlive as false on clicking New button before navigating away). But I want the form to be cleared without navigating. Can this be done?

You could have a screen/workspaceViewModel, and another ViewModel wrapping your data.
So two classes: CarScreenViewModel and CarViewModel.
The CarScreenViewModel would have a property, say CurrentCar, which reflects what is currently selected in the screen. Then, when clicking the Create button, you simply set:
CurrentCar = new CarViewModel();
Resetting partially loaded data will only lead to behaviour that is hard to reproduce. It is better to start with a fresh instance.

Your standard approach will be something like below
ViewModels
CustomersContainerViewModel which contains
a collection of CustomerViewModel s
and ICommands like
CreateNewCustomer
DeleteExistingCustomer
UpdateExistingCustomer
Your View will contain
the CustomersContainerView which will contain
a collection of Customer Objects in your required UI element
a button to Create new customer (which will launch a new screen which contains the newCustomer fields it can also contain cancel, which will just close the form)
a button to delete (can also be a ContextMenu)
a button to update (can also be a ContextMenu) which will launch a customer form filled with details from DB.
Hopefully this makes some sense... Let me know if you have problem with any of the above
Update - Forgot to add. NewCustomer Command will add a new Customer object to your CustomerCollection and that should open a NewCustomer form (or whatever you chose) for user to input the customer details. Cancel/Delete will just remove that record from the collection. Delete will update the DB as well in addition

In my case
yourViewName.variableName.postValue("")

Related

How to undo changes to passed parameters NavigationContext?

i have a Grid showing details of a Person object. When a row is selected, i am showing the details in a separate Region.
When the user edits e.g. the First Name Textbox in the Details View, the changes immediately get reflected in the Grid.
When the user decides to Cancel the edit, i can undo the changes by replacing the object in the Details view, but the changes in the Grid view are not reverted.
in OnNavigatedTo of the Details View i have:
_persons = navigationContext.Parameters["persons"] as List<Person>;
i make a MemberwiseCopy of _persons[0] and show _persons[0] in the Details View:
PersonEdit = _persons[0];
_savedPerson = _persons[0].Clone();
All fields of the details view are bound to PersonEdit.
Changing the FirstName, which is bound to PersonEdit.FirstName the Grid shows the changed value.
When the user presses the "Cancel Edit" button, i want to restore the saved Copy.
tried both:
PersonEdit _savedPerson;
_persons[0] = _savedPerson;
This restores the changes done before the edit in the Details view, but the grid stays unchanged.
Any ideas?
Thanks,
Helmut
I think you should invest some time in building an undo-(redo?)-infrastructure. Commanding comes to mind.
Until then, because of
When the user edits e.g. the First Name Textbox in the Details View, the changes immediately get reflected in the Grid
you should restore all the original values and the changes (i.e. the undo) will also be directly visible.
So do not clone and edit the clone, but keep the clone around and copy every editable value from the clone to the original object when the user clicks the undo-button.
Side note: if you use the default Clone implementation, you better be 110% sure that this is correct for your domain (and will be in the future).

How to edit properties of a ViewModel object but only apply changes when clicking a button in the View

My screen has a list of objects of type Person, and a form that displays the person properties (name, address, weight, etc.) via databinding.
I want to be able to:
Click in a button "Edit properties", and start modifying the person's properties (I can already do that using Commands in the ViewModel);
If I click "Cancel", the edited info "rollback" to the original unmodified values of that person;
If I click "Save changes", JUST THEN the person's name changes in the person list.
My problem right now is that, as I am editing the forms, the original properties are updated, so to say, in realtime, and if I decide to cancel, I have not the original values to "go back".
I considered to Clone the selected person, but that seemed to be odd. I think a better approach would be to change only the text properties of the field, and update back only when clicking to submit changes, but I don't know how to do it, specially how to preserve databinding consistency.
When you bind, use UpdateSourceTrigger=Explicit. That will tell XAML not to update the source binding until you tell it to. Then, when your Save button is clicked, you can call UpdateSource on the binding to push the contents of your controls back to the Person object, something like:
var nameBinding = nameTextBox.GetBindingExpression( TextBox.TextProperty );
nameBinding.UpdateSource();
To cancel, use UpdateTarget instead, which will push the data in the Person object back to your control.
You can try it with this Undo/Redo approch
http://blog.notifychanged.com/2009/01/30/using-the-viewmodel-pattern-to-provide-undo-redo-in-wpf/
Or
You could have a a Current and Previous property created in View model to which is going to hold the edited values and the other will have original value. The required action of rollback can be performed be reassigning the values
There are also open-source projects available to help with this, including http://undo.codeplex.com/

Optimal setup for warning user before exiting screen when changes have been made

I have a user control ProfileEditor in a WPF application. It has a number of input controls (TextBoxes, ComboBoxes, Radio Buttons, DatePicker). It will be used to add details for a new profile, or change details for an existing profile.
There is a requirement that if any changes have been made from the initial state (blank for a new profile, prefilled with current data for existing profile), if the user tries to leave the screen, they will first be warned that there are unsaved changes. This control will always be on a Page inside a Frame element, so leaving the screen will be either when navigating to a new Page in the Frame, or exiting the application.
What is the optimal setup for this?
I am thinking that there would be some event that would be attached to all data entry controls on the page (or maybe one event per control type) on the TextChanged or SelectionChanged events that would then set a page-level bool property as to whether or not changes have been made. Is there a way to set these using styles for all types of a control on the page at one time?
And then how would I catch the close screen event? Attach something to the Frame.Navigating event?

WPF trigger code behind button to display second form

I am a WPF novice.
I have created a form containing a combo box with which to choose a multi-field key value(populated from an XML data file).
I have also created a second WPF form which is available to display all field values from the record associated with the multi-field key value chosen from the first form.
I need to be able to click a button which will cause the second form to be displayed, with all fields filled in which are associated with the chosen key field values.
How do I go about writing such an event trigger using C#?
couple of steps (this is not really MVVM, BTW) ...
first, add a click handler to your button
second, in the click handler code, instantiate your new form
third, set the data context, etc for the new form
forth, show the new form by calling .Show()
in your xaml add a click handler to the button in question....
<Button Click="myClickHandler"/>
in visual studio, you can right click the text in the click="" and choose to navigate to the handler and visual studio will generate the code for it for you.
in your click handler, in code behind, do something like this....
public void myClickHandler(object sender,EventArgs)
{
MySecondForm form = new MySecondForm();
form.DataContext = theDataContextIWantToSet;
form.Show();
}

NullReferenceException thrown in NotifyPropertyChanged when switching views with edit in progress

I have a series of views that are to be displayed depending on the currently selected item in a tree within a parent view. These views are created and registered with the region during the initialization method of the parent view and are being correctly deactivated/activated, therefore giving the effect of swapping in/out the correct view. These views have a single underlying viewmodel as their datacontext, which contains data objects supporting INotifyPropertyChanged.
This solution works if there are no currently outstanding edits in progress within the child view but if there is a edit in progress in a view (i.e. the user has changed the contents of a description but hasn't clicked out of the text box) and that view is deactivated (i.e. the a different tree item is clicked within the parent view, thus causing a de-activation to occur) a NullReferenceException is being thrown in the NotifyPropertyChanged() of the underlying data object attached to the now deactivated view.
What seems to be happening is this:
An edit is started by the user in the child view
The user clicks an item in the tree in the parent view
The controller picks up the change in the selected item in the tree
The current child view is deactivated
The new view is activated
The change from the edit happens to the underlying data object (the set method is getting called)
A change notification event is generated by the data object as a result of this change
A null reference exception is thrown.
Presumably, this change notification event is being sent to the now de-activated view, but the view is not null.
I have not tried this myself, but I believe one solution was to listen for the deactivate event of the view using IActiveAware and cancel any editing.
See if this link helps.

Resources