WorkflowView force refresh when new child Activity is added - workflow

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.

Related

gtm.start firing twice (or more) on the same page causing two Container Loaded events

I have an issue on any page within a specific domain, where for every page load I have two Container Loaded events. Now this wouldn't bother me normally, but the DataLayer object I need only loads in the second gtm.start event, while my tag fires on the first gtm.start, so that the DLV is undefined when I need it.
Can I do anything GTM-side so that the DLV populates on the first Container Loaded event?
enter image description here
The container loaded more times than needed.
I think the problem is your website has 3 GTM installed. So the sequence here is very important.
You might need to check with your engineer or you can do it yourslef.
Currently the order looks like:
GTM-A.js
Datalayer you need
GTM-B.js
GTM-C.js
So I would recommend your order should adjust to
Datalayer you need
GTM-A.js
GTM-B.js
GTM-C.js
The core idea is make your datalayer push before any gtm.js code. This would make sure the GTM containers detect the datalayer you need when loading.
Otherwise. Make the datalayer push with an event name. So you can make your page_view event with that datalayer event.
But not very recommend this way. Only if you can not modify the order.

Issue with setting AutomationElement value

I have an issue with setting value of AutomationElement by using method ValuePattern.SetValue().
Everything works just fine until some dialog appears. When the dialog appears the code execution got stuck. No exception is thrown. After the dialog is confirmed, the code exection continues. Bellow is a sample of the code:
BasePattern basePattern = null;
ValuePattern valuePattern = null;
AutomationElement elementA = Window.GetElement(SearchCriteria.ByText(propertyName));
object patternObjectA = null;
elementA.TryGetCurrentPattern(ValuePattern.Pattern, out patternObjectA);
basePattern = (BasePattern)patternObjectA;
valuePattern = (ValuePattern)patternObjectA;
valuePattern.SetValue(optionToSet);
// Window.GetElement() is a method from TestStack.White framework
// The code execution got stuck on the last line until the dialog is confirmed
Is there any other way to set AutomationElement value?
Is somehow possible to avoid of getting stuck by dialog?
I'll by grateful for any help.
Thanks advance.
It could be that this dialog is not supporting UI Automation correctly or that you simply target the wrong element.
To verify that you may use Inspect.exe from Microsoft or similiar tools.
If it works, check if you really target the correct component with your code again.
If it does not work and:
if you are able to change the application
you can change the so called AutomationPeer of the UI component - here is a link for more infos
Or simply use another UI component that supports UI Automation correctly.
if you are not able to change the application, and also do not need to run in background, parallel, etc.. you might just focus the component (call setFocus() onto the AutomationElement, or expand it (via IsExpandCollapsePatternAvailable or simulated MouseClick onto the components coordinates)) and then use the SendKeys.SendWait("test") method.
EDIT: There is one more thing you should have a look at, and I wonder why I didn't mentioned it in the first place: Register to UI Automation Events
For example you could register a callback for the Structure change event type, and check if the dialog you talk about appeared.
If so --> click the confirmed button of the dialog.
Probably you will have to synchronize your execution, so that every further action in the UI Automation script waits until the registered callback got executed and the confirmed button got clicked.

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.

How to view updated data on one property page updated by another property page without closing the properties in eclipse plugin?

I am facing a strange issue!!
I have a set of property page with same storage file.
The scenario is as follow..
For the first time opening the properties by right clicking on the project, list of property pages are viewed. I click on the first property page and make changes then apply the changes to the file.
Now I select the second page, it shows the changes that were applied from the first page.
But now without closing the properties i go back to first page and make changes then apply the changes.
Then again I go to second page it wont show the updated data. The changes that were applied are not viewed until I close the properties and reopen then by right clicking on the project.
My question is
"Is there any way to reflect changes on the pages without closing the properties??"
I appreciate your valuable time you will give for reading and replying..
Plz help
Your problem seems to just absent of reliable model which can notify problem.
If the properties are related IProject.
You should use ScopedPreferenceStore as model.
IScopeContenxt scope = new ProjectScope(myProject);
IPreferenceStore store =
new ScopedPreferenceStore(scope, "myProperties(qualifier)");
IPreferenceStore can manipulate primitive data, default value. And it support property change event. You can create multiple instances of IPreferenceStore, If they have same scope and qualifier then automatically synchronized. So individual page can retrive input model without coupling.

How do you update a JFace Viewer from inside a Job?

Caveat: I'm still struggling with proper MVC in Eclipse plugin development, so if you see anything here that is most likely causing me more pain that I should be enduring, please let me know.
The question:
I have a View with a JFace Tree Viewer and a Table (not a table viewer... that will be changed down the road).
I have an action that is initialized with a reference to the View (this seems terrible to me, but I don't yet know how to do it the right way). When the action is run -- via a button on the view -- the action:
1) gets the Tree Viewer from the View
2) gets the underlying model
3) creates a Job
a) inside the job, loops over the model and does various things to it, including adding additional children into the model
b) uses a function exposed in the view that "clears" the Table in the view
4) adds a JobChangeListener that implements "done()".
a) inside the done() method, it expands the treeviewer via this code:
loadMethodsJob.addJobChangeListener(new JobChangeAdapter(){
public void done(IJobChangeEvent event){
view.enableActions();
view.getTestsViewer().expandAll();
}
});
Inside the Job, whenever I attempt to access the elements in the viewer, I get Invalid Thread Access errors. I believe I understand why I get them when running inside the job, but I'm not sure how to work around them correctly if I can't interact with the widgets in the job change listener. I can get it to work if I wrap every interaction with the widgets in a getDisplay().synchExec(....), but I seem to remember reading that this is not preferable.
I feel like I'm on the cusp of a big leap in understanding with Eclipse SWT, so I appreciate any guidance in getting there.
Any UI component in SWT can be accessed only by a UI thread.
Since the done method of the job runs in a separate non-UI thread, the invalid thread access is fired.
By wrapping every interaction in a Display.syncExec , you are making sure that it runs in the display thread (The UI thread).
There shouldn't be any problem with the above approach.