Update image in ViewModel2 when it is changed in ViewModel1 - c#

I have the following setup (this is my first foray into MVVM and I am trying to switch over from using code-behind):
I have Contacts. There is a window showing all the contacts. On the left side is a ListView that has a list of ContactCard each ContactCard can have an image.
To the right of the list is a ContactDataDisplay which shows all the information about the selected contact including the same image as in the ContactCard. Inside the ContactDataDisplay is an EditableImage. These are just images that are overlayed with 2 buttons, "Update" and "Remove", when the user hovers over the image. The EditableImage has its own ViewModel (as it shouldn't be tied to only Contacts
I have it wired up properly so that the image updates in the ContactDataDisplay using bindings, (which is easy since it all occurs in the same ViewModel). However, I am stuck on how I can get the ContactCard image to update considering that it has an entirely separate ViewModel.
I tried to add a click listener to the button in the EditableImage and update the ContactCard with the new image in code behind, but I can't force the order of the method call as far as I know, and this seems to go against the point of MVVM.
How do I connect my ContactCardViewModel and my EditableImageViewModel so that the ContactCard image changes, without passing the actual Contact object that is being bound to in my ContactCardViewModel.

You should try using Event Aggregator Pattern.
https://social.technet.microsoft.com/wiki/contents/articles/23314.using-the-event-aggregator-pattern-to-communicate-between-view-models.aspx
In this case ViewModel1 will be the publisher and ViewModel2 the subscriber.

Related

How to display MainWindow before the business logic execution has completed

So I am new to MVVM with WPF and am having trouble with a few concepts.
So as soon as you run, my MainViewModel will set up the model and will start pulling from the database in order to populate a list which is binded to one of my controls.
Now the problem is that, after it pulls data from the db it then needs to listen to another source which will fire an event and then add to this list. Now, this data source will fire events infinitely, so I would like to display the UI with the DB-pulled data and then update this list as events fire.
My initial idea was to only start this listen for updates once I have loaded and presented my control, but how is this done using the OnLoaded event in MVVM, I think this has been my biggest struggle.
Thanks
Decided to go with Clemens' comment.
I now, bind the datasource in code and run the viewModel's listen method when the window is loaded, using the Loaded event. I am still not sure if this is a good MVVM solution so will probably change it again soon if it isn't.

Create a UserControl from a Model - Share ViewModel Property between UserControl

I have created an UserControl that encapsulate two UserControl.
The first one is a "model" that can be changed by the User. It represents a ObservableCollection of TextBox. Each one of them is filled by the User.
My second UserControl will be a List of UserControl.
Each sub UserControl will be a list of textbox.
I want to be able to create my second UserControl by using the information of the first UserControl ==> Text in each Textbox used in tooltip of textbox.
So what I want is when the user add a field in the first usercontrol to be able to add the same field in each item of my second UserControl.
The black rectangle represents my model and the red rectangle represents my second usercontrol so the use of my model to create a UserControl.
Each UserControl owns his ViewModel.
Thanks in advance.
Hi please try the next architecture:
First User Control observable collection. The ObservableCollection supports event which will be raised when item will be added/deleted/etc. Submit on this event in your first user control view model.
Second User control let its view model be composed of ObservableCollections.
Share the EventAggregator (link here) between view models of your controls. First user control view model will be publisher and the second will be subscriber.
Each time when the observable collection of the first user control view model will be changed, publish the aggregator event to inform about the fact that this collection was changed.
Second user control will get the event and perform action (add/delete) on all its collection.
update
You can manage the sharing mechanism so that the EventAggregator will be the same reference, but the published object will have a key which represents a particular tab (for example the hash code of the tab), thus each subscriber will know if it have to response or not.
That's all. Try to perform that, I'll be glad to help if you will problems with the code.
Regards.

Updating a particular item in a databound collection

I have windows phone 8 app which displays a persons pic and his details sent from server (something similar to a contact book).
The way I have implemented this, is by storing images from server in Isolated Storage with a unique name, and then adding this unique name and person's information in database.
I implemented the GUI, by binding the database to a LongListSelector (using Observable Collection). LongListSelector's item template has an Image control and I use ValueConverter class to translate the unique name from database to the physical location of the image. When server sends an update to personal information, I can simply update the database and data binding will update the UI automatically. Until here everything works perfectly.
Now I have this scenario :
When the server sends an updated image, I can only update the isolated storage. How can I let the GUI know that image is updated? I am not sure how to make use of databinding here, since the image name doesn't change and there is no update process in database table.
Is there a way other than reloading the entire collection?
I guess that the class bound with the UI is acting like a ViewModel and is implementing the INotifyPropertyChanged interface or some derived class (ViewModelBase for example if you're using MVVM Light).
In that case, you should raise the ProperChanged event (or call the RaisePropertyChanged method in MVVM Light) with the name of the property bound with the image control in order to notify the UI that the data has changed. The converter will be called again and the image will update.

creating a custom user interface in WPF

I have a SQL database holding a number of numeric and text values that get updated regularly. The exact number/type/names of these data points can change depending on the source of the database writes.
I would like to create a user interface editor, where the user can add database points to the UI and arrange them and format them as they want. If a new point is added to the database they can right click on the UI and say "add this point" and choose from a list of database points.
I'm looking for some pointers on where to start on creating this editor application, could something clever be done using XAML to dynamically create std WPF controls at runtime?
Doug,
Apologies, by database points I simply mean rows in the database that represent an item to be displayed in the ui.
Ray / Sushant,
Thanks for taking the time to answer, I'll have a go at both these approaches.
Si
Here is an easy way to do this:
Create a DataPoint class, including "Name", "Type" and "Value" fields
Create a DataPointView UserControl that exposes a Name property and a read-only DataPoint property. When the Name property is set, load the DataPoint from the database. Optionally use a timer to periodically reload the DataPoint (or subscribe to update notifications from your database).
Create a UIEditor class deriving from Window that exposes a CurrentForm property that is initially a blank Canvas
Add handlers for ApplicationCommands.Open, ApplicationCommands.Save, etc to use XamlParser and XamlWriter to load/save the layout from/to a file on disk (or a database)
In your UIEditor XAML, include a ContentPresenter bound to the CurrentForm property to hold the UI being edited. Also any other controls desired (Save button, Open button, palette, etc).
In your DataPointView's XAML, display the data point's name and value.
In your UIEditor class subscribe to mouse preview events OnPreviewLeftButtonDown, etc. Whenever a mouse move event follows a mouse down event on a DataPointView, capture the mouse and begin adjusting the DataPointView's Left and Top coordintates - this allows the user to drag the DataPointView around the Canvas.
In your DataPointView's XAML, include a ContextMenu whose ItemsSource is bound to "{Binding AvailablePoints, RelativeSource={RelativeSource FindAncestor,my:UIEditor,1}}", and make sure the AvailablePoints property of your UIEditor class returns a list of MenuItems with names of available data points and appropriate command an command parameter.
In your handler for the command bound in the context menu, add a new DataPointView to your CurrentForm Canvas and set its Name from the name given in the CommandParameter
Set Focusable=true on the DataPointView objects, and handle ApplicationCommands.Delete by deleting the focused DataPointView.
With this code written:
You can allow your users to edit your UI by showing a UIEditor window.
You can display your UI without the editing features by simply loading it from disk using Application.LoadComponent and displaying it in a window.
use WPF DataGrid available as WPF ToolKit in .NET 3.5 or it is standard for .NET 4.0. It has the following features:
Highly customizable Data columns
Use Editable Rows that can be persisted
Columns can be added/deleted/rearranged on the fly.
Can directly load column names from database
and a lot more.
I think that would be perfect.
Please mark the answer if it seems helpful. Thanks.

How to implement CRUD Master Details on the same screen under MVVM

I have a MVVM (Prism) application that I need to implement a master details screen wheer the master is a listview and the details is displayed next to it. Read-only seems easy enough (haven't done it yet but I've got my head around WPF binding) but edit/add confuses me.
How to I make it so the master is not updated until the details is saved?
How do I make it so you can't change the master's current selection while in edit/add mode?
I've been googling a plenty but have not found any meaty examples of this.
Thanks.
PS: This view is a child view on a larger screen. This is why I want both master and detail together.
You certainly can do this, though in my opinion such a UI design fails to harness the full power of WPF. Old WinForms UIs usually didn't update most of the application until data was saved to SQL Server (or wherever) because they didn't have real business objects and a powerful binding system like WPF. Trying to copy WinForms limitations within WPF seems like a step backward to me. Why not show the latest data everywhere it is visible in the UI, including in the master view? Also, why not allow the user to edit multiple items before saving, for example marking any edited but unsaved item with an animated marker in the master view? Combine these with a generalized undo and you have a better design and more intuitive for the user.
However if your business requirements make it absolutely necessary, here is how to do it:
Preventing changes to data from being visible outside the detail until it is saved
Upon entry into your "edit/add mode", make a copy of the data objects and set your detail view's DataContext to the copy instead of the live object. When the data is "saved", copy the data from the shadow copy back into the live object and set your detail view's DataContext back where it should be.
Preventing the master's current selection from changing while in edit/add mode
Two possibilities:
During edit/add mode, change the master view to disallow mouse hit testing or keyboard focus
When edit/add mode begins, capture the "current selection" then add an event handler that watches for "current selection" changes and immediately changes the selection back to what it was. When edit/add mode ends, remove the handler. This handler can be conveniently coded using a lambda expression and using a closure on a local variable to store the current selection.
Thanks for the answer. Now I've re-read my message, I see it is rather vague. I have a screen that edits an object which contains multiple lists of other child objects. I've implemented these as different tabs in a tab control. One of these tabs edits the comments, so I wanted to display a list of comments with an edit panel for the current selection next to the list. The user could then use add, edit or delete buttons to update the list. I wanted to do this in a pure(ish) MVVM way.
I came up with the following design which seems to work with minimal hacks.
The View includes a list of the child objects simply as a ListView bound to an observable collection within the ViewModel. I included a child object buffer – this is used to buffer changes until they are ready to be saved back to the list (or thrown away).
The View also includes an edit panel bound to the buffer object in the ViewModel. The buffer is updated whenever the list view’s current selection changes using a deep copy. I tried using data binding on the Selecteditem property but the set was never called, so a small code-behind method was added to force the property to be updated when the selection was changed.
The list view and edit view are mutually exclusive. In theory you could hide the disabled one, perhaps using a flip screen. As a general pattern, it is better for my app to have both visible at the same time as the edit panel may show extra information not shown in the list view. The choice as to which panel is enabled is controlled by binding IsEnabled to a ViewModel property like IsEditCommentMode.
Commands to manage the list have to be added, these are New, Editand Delete. Note that Add and Edit will set set up the buffer then set IsEditCommentMode to true. These list management commands are only available when IsEditCommentMode is false.
The edit panel implements Save and Cancel commands, they are only be enabled when IsEditCommentMode is true. When Save is executed, it should copy from the buffer to the list (either add or update) and fire the change notification. Finally, it should set IsEditCommentMode to false.
This all works well and does not seem to violate any MVVM tenents (in my humble but often flawed opinion).

Categories

Resources