WPF : update parent form after canceling edit in child form (reset DataContext) - wpf

I have a parent form with a customers listing in a WPF datagrid.
Editing a line of the form is done in a child form: click on a button in a line, open child form using selected item of datagrid and assign it to child form datacontext.
When a PropertyChanged event is triggered in the child form, the line being edited in the parent form listing updates.
If I decide to cancel my current modification by clicking on a cancel button in child form, I restore the original values ​​of the edited customer: before editing I made a clone of to be edited customer. Then now I reset child form DataContext by setting it to null then to the cloned customer. This was the hack I read on SO about forcing DataContext to refresh with DataContext itself being changed, not properties on its objects.
After canceling edit, child form shows the values I expect (properties of cloned customer), while the associated line in parent form listing didn't update: still shows edited customer values.
How can I ask parent form to update itself? I'm afraid I lost some references between objects by reassigning child form datacontext to a new object (loosing link to parent form datagrid interesting line selected item).
Thanks for your guidance,
EDIT :
When I am ready to edit a customer in child form, I assign datagrid selected item to a static variable of my application since it's mono-user, so that it's easier to handle "current customer". When I cancel edition, this static variable value has changed, but maybe I have to assign it to parent form datagrid selected item back too?

I was right: after child form closes, I must update parent form datagrid collection, at right index, with updated object.
// update static variable
SocodifApp.Client = ((Client) Listing.SelectedItem);
ClientForm editClientForm = new ClientForm();
editClientForm.ShowDialog();
// Get modified static variable after child form closes and update datagrid collection
// relevant item
_dataContainer.Clients[Listing.SelectedIndex] = SocodifApp.Client;

Related

WPF DataContext issue with datacontext object

I have created a simple sample with datacontext. Please get the sample from here : source I understand that the uses of DataContext is
If the user change any content in UI, it should be updated in the back end datacontext class without any additional work.
If we make any change in back end datacontext object, it should be updated in UI without any additional work.
In my sample,
If I click "click" button, the textbox value gets updated. - pass
If I click "update" button, the textbox value gets updated. - pass
If I click "clear" button, the textbox value not updated. - fail
After clicked "clear" button, If "click" or "update" button is clicked the textbox value not updated. - fail
Am I doing anything wrong? If yes, how can I initialize some value in the textbox in constructor, and after that if the user make changes, the datacontext object values need to be updated. If I update any value in code behind, the values need to updated in UI. Also if I click "clear" button all the textbox values need to be cleared. After that if user enter value again, the object need to update. How can I achieve it? Please help.
Note: In my sample I have commented some lines. In that i have casted the datacontext to the model class every time and changed it. Its working fine. Do i need to use that method to update values run time. Changing values in object will not update in UI?
The problem is that you consider the variable 'dc' linked to the DataContext, but that is not the case. To fix your code simply set the DataContext again after you change the 'dc' variable.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
dc = new Journal();
myPanel.DataContext = dc;
//myPanel.DataContext = new Journal();
}

How to reset a viewmodel in mvvm

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("")

wpf datagrid : remove dependency between main listing / child edit form?

I have the following : a datagrid which DataContext is an object with a list of Customer objects. I pull the values from database.
To edit some customer, I click on a button in a row and open a new form with customer details. For now I pass the relevant customer object (thus reference) to child form DataContext.
I'm not fine with this because any modification in customer form are show in customers listing form.
I'd like both to be independent, and get customers listing form data refreshed only when I click on "save" button in child form (nothing done when I click on "cancel") that will trigger database reading for edited customer updated values.
Tell what you think would be right apart from these ideas :
Make a clone of Customer object and pass this clone to child form. I'm not fan of this.
Reread customer to edit from database to have a complete new object with relevant data. Seems not fun to ask to database again since my customer data is already completely read, in this case.
Thank you for suggestions.
I went on with my own way of doing this without working with delegates : WPF : update parent form after canceling edit in child form (reset DataContext)
A bit cumbersome but works.
I also used this nice way of cloning: WPF : update parent form after canceling edit in child form (reset DataContext)
But I did some changes: I added "where T : class" to the generic method signature.
I also simplified the code for testing for a null parameter :
// Don't serialize a null object, simply return the default for that object
if (source_ == null)
{
return default(T);
}

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.

Windows Forms ComboBox problem

I have a combobox that goes out to the database to load it's content on clicking the dropdown arrow. if after the dropdown box is shown with data and I don't select anything, than the current value of the combobox is blown away. Inside my routine to load data, I tried saving the current value and restoring it back after the loading is done. doesn't work.
[Edit] Added the code from the comment here for legibility
MyUltraCombo myultracombo = new MyUltraCombo();
//MyUltraCombo inherits from UltraCombo inside MyUltraCombo, I keep the table name to load from
MyUltraCombo.BeforeDropDown += new System.ComponentModel.CancelEventHandler(cb_BeforeDropDown);
//inside the eventhandler
myultracombo.Load();
//inside the Load method
datatable = DataUtility.GetAllRecords(tablename);
combobox.datasource = datatable;
If you store "the current value" as just the SelectedItem property, then it will probably not be an object that is present in the new list, since it will consist of completely new objects. What you will have to do is store an ID of the current value (if you're lucky to have a unique id) and then search the newly created list for an object with the same id (or whatever you use to uniquely identify an item, maybe just ToString()...).

Resources