Best way to update view from command or filedialog in an eclipse rcp application - eclipse-rcp

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.

Related

How to trigger an event as soon as we launch the view in SWT

I have an RCP application where I am creating a view which invokes an instance of the composite.Now my problem is I want to trigger one event as soon as I show the view/composite in the screen.
I tried with addFocusListner(),addMouseTrackListener(),addMouseListner()but unfortunately none of the them gets the control as I move my mouse pointer around the view.Is there any way we can solve it?
Just grab the control you have used to create view and add selection listener on it.
for example if treeViewer is used to create that view then:
treeViewer.setSelection(new StructuredSelection(element),true);
Ensure selection by this treeViewer.getControl.setFocus();
If you want to trigger an event after your view is in focus/launch then you should add a listener to that view e.g IPartListener2for that you need to create a class and implement IPartListener2 interface. you will get more information here
Also if you want only using mouse event then you need to add MouseMoveListener to your view so when mouse pointer on your when mouseMove will call.
e.g. control.addMouseMoveListener(this);

How to communicate from ViewModel to View

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.

VM role in MVVM - should it handle everything and why?

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.

Updating a view from a command handler

I have a file dialogue opening from the menu where a user can select a file. The FileDialog is called from the menu command's handler class in execute().
Based on the file the user selected, I would like to update a view, for which (I believe) I'd need the same Composite element that's passed to the view in createPartControl().
Is it possible to get access to it from the command handler, or would it be better to trigger the view updating via something like ISourceProviderListener or PropertyChangeListener?
Thank you.
Yes, it's possible:
IViewPart part = HandlerUtil.getActiveWorkbenchWindow(executionEvent).getActivePage()
.findView(viewId);
It would be better to first update the data that your view is displaying (the model in MVC) and the change in data should trigger view refresh. It's hard to say which listener is better without knowing all the details.

Eclipse Plug-in / View Question

I have a plugin which contains class A that brings up a view defined in class B via the following line of code:
(VideoLogView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("Videolog.VideoLogView");
What I need to do in the createPartControl() method of the view (class B object) is access a method in the class A object.
How can this be done?
Thanks.
Look like you are facing the classic issue of "how do I pass arguments to my view" ?
This thread illustrates it best:
I was facing the same problem at the beggining of my RCP project. I was getting weird about the fact that there was no way to pass an argument to a view as the viewed model.
Why? Because (emphasis mine):
You are on an opened, pluggable platform.
You contribute to existing developments, others should be able to contribute to yours.
Therefore you will not "pass" arguments to a view, this would lock the whole thing into a non-opened design.
Instead, your view will ask the platform (or will listen to the platform) to determine which information to manage.
Other views (from other plugins that don't yet exist) might also want to manage the same information on the same event.
What you should do then is to ask the workbench for the current selection. I guess your view is opening on a double click action or simple selection so the object you want to manage in your view will be currently selected.
This is how you could retrieve the workbench selection from your view :
ISelection s = this.getSite().getWorkbenchWindow().getSelectionService().getSelection();
where "this" is a ViewPart.
Then you have to make your initial view (the one initiating the view creation from a given event like DoubleClick) a selection provider. A JFace viewer is a selection provider, so you can use it if you're using jface, or you can implement the ISelectionProvider interface when you're using custom SWT controls (that was my case).
The article "Eclipse Workbench: Using the Selection Service" can also give you some pointers.