I have a property on my ViewModel called LostFocus, and I want the View to know when this changes so that it can act on this info if it pleases (i.e. maybe the designer of the view might make it blur if LostFocus is set to true, or maybe they won't do anything).
I'm using Caliburn.Micro, so if it has any features I should be aware of here please do tell. Otherwise, how would you go about doing this in an MVVM fashion?
This can be accomplished with ordinary data binding as I understand it. Since you're using Caliburn.Micro, the designer can use conventions to do the binding. For example, if there were a check box control on the view that was to be checked when LostFocus is set to true, the designer would just have to ensure that the Name property of the check box was set to LostFocus and then Caliburn would set up the binding automatically.
Also, on your View Model, make sure you raise the property changed notification event when you change the value of LostFocus.
You could also, rather than using a LostFocus property, create a LostFocus event on your view model. You could then raise this event whenever you feel it's appropriate and then, on the view, the designer could respond to that using an event trigger and trigger action. For example, on one of my projects, I set up an event trigger to respond to the view model's Activated event and then I wrote a custom trigger action to play a storyboard that was responsible for doing the view's intro animation. This approach isn't restricted to Caliburn.Micro, but I did use it on a Caliburn.Micro project, so it definitely works.
I ended up learning about the BindingConverter and used that to convert a boolean property of false to null and true to a BlurEffect.
Related
In my application I have a menu which open a SelectionDialog, this dialog is used to choose an object.
When this object is selected I have to display it in the view.
What is the best way to update my view?
Currently, I call myview.update(object) after the dialog is closed (in the handler of the menu). But I think this solution is not well design.
I have read about update my model and notify my view but my model does not change (no data are changed, I only display different Data ).
Does anyone has some ideas for a well design solution ?
Define model listener ( dataPopulated(Event e))
Make your view implement model listener and register it with the Model.
Define a Model class that can contain the objects that you want to populate in the view
When Model.setInput(Object input) is invoked fire dataPopulated() event on all registered model listeners.
Above steps works properly when you have view activated. You need to consider cases like when if view is deactivated or not visible ( make sure you refresh view is visible else you will have unnecessary overhead of refreshing view though it is notvisible)
Try adding a selection listener in the view and register this selection in the dialog.
In the listener action, add the code to show the selected object.
Where exactly is the limit to adopt VM so it can suite better a particular View? Example:
There should be a command in UI (ex button) that should allow adding new item. Additional requirement can be that new item should be selected, ensured that its visible on control (lets say TreeView control), and to begin edit on the newly added item (in order to change predefined value that was set in VM). Lets assume that control doesn't have automatic mechanism to achieve this, so we need to do it manually. So the execution flow looks like this:
invoke add command on VM - done is View's xaml.
set SelectedItem to new item (usually we bind control's SelectedItem property to VM's CurrentItem property, and then just assign new item to CurrentItem.
ensure that new item is visible on control - this must be done in View's code behind.
Start editing - this must be done in View's code behind.
Now, since everywhere on net there are articles on using messages for almost everything, a question:
What do I break if I do it in the simple old fashion way? I use Click event instead of Command binding on adding new item, and in the method I do this:
// in View's Click event handler
ViewModel.AddCommand.Execute(null);
EnsureVisibleSelectedItem();
BeginEdit();
.. clean and clear! And what do I gain if I do it using messages:
// in ViewModel's AddCommand
AddNewItem();
SetCurrentItem();
SendMessageToEnsureVisibleSelectedItem();
SendMessageToBeginEditSelectedItem();
... where View has registered to receive these two messages.
Any light on this is greatly appreciated. To my opinion, UI can change, and VM should be able to adopt new UI without making changes to itself, so I dont quite understand current MVVM policy that is preached on internet.
I would say "make it simple".
What's really important in MVVM is:
what doesn't depend on the view should go in the ViewModel (your ViewModel must not be aware of the view in any way - not just by object reference)
everything else in the View and its code-behind.
Yes, in its code-behind. There's nothing wrong in writing code-behind if it is code that is related to the view, not logic. For instance, drag & drop management should be written in the code-behind.
To answer your question, you do not break anything in writing:
// in View's Click event handler
ViewModel.AddCommand.Execute(null);
EnsureVisibleSelectedItem();
BeginEdit();
Everything that is not related to the view is in the ViewModel, everything else in the View/code-behind. That's just fine.
No if I look at your second example:
// in ViewModel's AddCommand
AddNewItem();
SetCurrentItem();
SendMessageToEnsureVisibleSelectedItem();
SendMessageToBeginEditSelectedItem();
AddNewItem is OK (not related to the view), SetCurrentItem is OK (not related to the view), but what about SendMessageToEnsureVisibleSelectedItem and SendMessageToBeginEditSelectedItem?
EnsureVisible is typically useful for a treeview, but what if your view wasn't built with a treeview? What if the control would automatically make the new selected item visible? Of course you could ignore the message, but you would have written some useless code in ViewModel because you thought your view would need it for UI display.
You have typically written here some code in the ViewModel that is aware of how the View should be working. Yes, you have reduced the number of lines in the code-behind, but you definitely have broken the pattern.
Your "old fashion way" is actually a good way for your needs. Your ViewModel is not aware of the view, that's what's important.
Consider these two scenarios:
a user presses a button in a view (e.g. Fulfill Order) and we want the view to update immediately (disable the button, add a progress bar, etc.)
a service layer raises a business event, which ultimately must be reflected on the view (e.g. a product has become out-of-stock).
Both cases legitimately require some mechanism, X, to update the viewmodel. With MVVM, the view can do this by setting properties of the viewmodel in an event handler, through command binding, or via some other mechanism.
The service layer can do this using some mechanism, Y. For example, raising events in the business/domain model, creating commands to manipulate the viewmodel, calling methods on the viewmodel etc.
In fact, X and Y could be the same mechanism (or pattern).
What's a good one to do this, that keeps to the spirit of MVVM, but is DRY?
I think you need to pick an MVVM framework and follow the pattern for this that it supports.
In general:
Your button will be hooked to a FulfillOrder method on your ViewModel, via an ICommand or whichever your MVVM-framework supports
A "CanFulfillOrder" boolean property will be hooked up to disable your button via INotifyPropertyChanged, this can be triggered by the FulfillOrder method or the event you mention. It could also be bound to the Visibility on a progress bar.
Another property could provide the percentage on the progress bar and update it appropriately
A good, general-purpose MVVM framework is MVVM Light.
If you are looking for more power, and can handle more complexity, try Caliburn.
Or if you want to use dynamic and try something cutting edge, try my framework: NoMvvm.
I am doing a silverlight using the MVVM model, and i am finding it hard to do the events handling via MVVM especially that the events handlers are doing lots of changes in the view like enabling and disabling buttons, update media element functions and position. I am still new to the MVVM and i can't Imagen how can i do this. does anyone already know good article to start with or simple approach to understand :) I'll reply with what i may find interesting while i do my search as well. Thanks
1) Understand that there are different "flavors" of MVVM. Strict/hardcore MVVM patterns, although theoretically desires, isn't necessary.
2) Many view events can be handled via Commands. WPF supports this, and i believe Silverlight 4 does as well. A simple view-event to start with would be Button clicks. This allows you to handle the event in the ViewModel (instead of the View's 'code-behind').
3) For things like enabling/disabling view controls/states via the MVVM model, here is an example/explanation:
Xaml controls (say, a Button) is Data-Bound to the ViewModel for whatever property
(in this case, it will be the button's IsEnabled property).
Your ViewModel has an IsButtonEnabled property.
Whenever you change this property in the VM, raise the PropertyChanged notification, and you will see the binded result in the view (the button's IsEnabled state will be updated).
ps - you can do many things via VM properties in this manner: from text, to various property states, color, you can even play animations in the property setters/getters....etc.
Cheers
My application is using workflow designer rehosting to let end-users develop workflows. I have an Activity available that requires the user set some state. To accomplish this, in the designer I override Initialize(Activity) and show a form which I then use to set values in my Activity. This is for setting the state when the Activity is initially added. I also have a double click event handler in the designer in case they need to edit that state later.
I now have a situation where, depending on the values in the form, I may need to add or remove a child activity. I've been successful in adding the activity, but not always in getting it to show up in the designer.
When Initialize is called, there are no child activities. I may need to add a child Activity. At this point, it works fine and shows up in the designer. The problem happens when they edit it later by double clicking. In my designer, I override OnActivityChanged to detect this. I make the same call to add a child, however the designer is not getting updated. Oddly enough, when the situation is such that the child is removed, the view updates fine.
Stepping through with the debugger shows that I am adding a child activity to the Activities collection. Normally when I have problems updating the view, I can make a call to IComponentChangeService.OnComponentChanged, but I can't seem to find a way to make this work.
Any suggestions?
It looks like I needed to use RemoveActivities and InsertActivities in the designer. It seems as if the designer doesn't listen to list change events on the Activities list. Does anyone know if this is how it's supposed to work?
Have you tried this in your OnActivityChanged event handler?
TypeDescriptor.Refresh(e.Activity);
For my situation, I determined I needed to use RemoveActivities and InsertActivities.