How to extend the context menu inside the rehosted workflow designer? - workflow-foundation-4

We are using a rehosted designer (currently WF 4.0) with a lot of custom activities, all of them have custom designers. For a bunch of them, I would like to add entries to the context menu of the designer when in design mode. I'm talking about this menu:
E.g. for a XAML coded activity I would like to have an "Open source..." entry which will load the XAML source of that specific activity into a new designer. To do that I must add the entry to the menu, and when clicked figure out on which activity it was clicked. Both parts are unclear to me. How can I achieve that?
In WF 3 there was the ActivityDesignerVerb class to do that. In WF 4 there seems to be workflowDesigner.Context.Services.Publish<ICommandService>(...), but I can't figure out how to use that to add a custom action to the context menu. How can I do that?
This SO entry shows something for internal debugger commands, but I want to add a completely new command.

Solving it in the host
If you want to solve this on the workflow designer host, and not in the individual activities, it's quite simple and straightforward to do this.
When you host the workflow designer and create the workflow designer, you can simply access its ContextMenu property and modify its Items collection.
var wfd = new WorkflowDesigner();
wfd.ContextMenu.Items.Add(new MenuItem() { Header = "Hello", Command = yourCommand, });
If you want different menu items for each activity, you can subscribe to the SelectionChanged event:
wfd.Context.Items.Subscribe<Selection>(SelectionChanged);
And then implement your own logic:
private void SelectionChanged(Selection selection)
{
// Remove old menu item
if (oldMenuItem != null)
{
wfd.ContextMenu.Items.Remove(oldMenuItem);
oldMenuItem = null;
}
var modelItem = selection.PrimarySelection;
if (selection.SelectionCount == 1 && modelItem != null)
{
// Get activity type
var activityType = modelItem.ItemType;
var menuItem = new MenuItem() { /* ... */ };
wfd.ContextMenu.Items.Add(menuItem);
oldMenuItem = menuItem;
}
}
Solving it in the activity designer
If you want to always show a specific context menu item regardless of where your workflow designer UI is hosted, you can create a custom item in your activity designer XAML:
<sap:ActivityDesigner.ContextMenu>
<ContextMenu>
<MenuItem Header="Show" Command="{Binding YourCommand}"/>
</ContextMenu>
</sap:ActivityDesigner.ContextMenu>

OK so all you need to do is implement the ICommand interface on your custom activity.
So, for example - expose a custom command property from the customer activity class, then in the constructor apply a delegate event to the command handler -
/// <summary>
/// Custom activity
/// </summary>
public partial class CustomActivityDesigner
{
/// <summary>
/// Command used to display a dialog at design time
/// </summary>
public ICommand ShowCustomDialog{ get; set; }
public CustomSchedulerDesigner()
{
InitializeComponent();
ShowCustomDialog= new DelegateCommand(x =>
//Do some stuff here that will display your dialog
//you may want to consider passing the `this.ModelItem`
//to your dialog so it can then interact with the ModelTrees etc
//for example
var dialog = new MyDialog(this.ModelItem);
dialog.ShowDialog();
);
}
}
Finally,
hook the new command up to the UI via the activity designer xaml.
<sap:ActivityDesigner.ContextMenu>
<ContextMenu>
<MenuItem Header="Show" Command="{Binding ShowCustomDialog}"/>
</ContextMenu>
</sap:ActivityDesigner.ContextMenu>

Related

Manually Open custom inspector for serializable object

I have a window editor that holds nodes. I would like to open a custom inspector when one of these nodes is selected. The node class is a custom serializable class. Is this possible?.
It seems that custom inspectors can be created manually through the Editor.CreateEditor method but can't see how to let it appear docked like an usual inspector in the unity inspector window.
I would like to achieve the same behaviour that we have when we select a gameobject in sceneview that inmediately show properties for the object (Components, etc...) in the unity inspector.
Cheers
As I'm not sure what you're asking, here are multiple different solutions;
Selection
If you just want your nodes to become the focus of the hierarchy, then in your custom window's OnGUI method, use the code below;
[CustomEditor(typeof(NodeManager))]
public class NodeManager : EditorWindow
{
private static NodeManager window;
private Node[] m_nodes;
[MenuItem("Custom Windows/Node Inspector")]
public static void Init()
{
if(window == null)
window = GetWindow<NodeManager>("Node Manager", true, typeof(SceneView));
}
public void OnGUI()
{
m_nodes = GameObject.FindObjectsOfType<Node>();
foreach(Node node in m_nodes)
{
GUILayout.BeginHorizontal();
{
GUILayout.Label(node.name);
if (GUILayout.Button("Select"))
Selection.objects = new Object[] { node.gameObject };
}
GUILayout.EndHorizontal();
}
}
}
This adds a Button for each object in your custom window view, that will then select that object in the hierarchy.
Auto-Docking
I originally found the second response to this question, which goes into the details of parameters of the GetWindow method, and with this you can clearly see how to dock the window (I've converted it from JS to C# below).
(I looked fairly extensively in UnityEditor and UnityEditorInternal namespaces but couldn't find the Hierarchy or the Inspector).
GetWindow<T>(string title, bool focus, params System.Type[] desiredDockNextTo)
Which we can write for this example as;
EditorWindow.GetWindow<NodeInspector>("Node Test", true, typeof(SceneView));
This example docks the windows next to the SceneView window. This functionality can be combined with a custom inspector's OnInspectorGUI method, to automatically launch the custom node window, if it's not already open.
[CustomEditor(typeof(Node))]
public class NodeInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
NodeManager.Init();
}
}
Sorry if this isn't what you are looking for, if it's not then please give more details and I will amend my answer to better suit the question.
Hope this helped.
Has a possibility, you can make a custom ScriptableObject and Custom Editor for It, and when open the node inspector, just find a instance of the scriptable object and use Selection.selectedObject = scriptableObject, and in the custom editor, make a static field called 'editor' to draw inside.
It will work.

android tv -Reference of search image in browse fragment

I have a scenario where I need to set focus dynamically on search icon in browse fragment .For that I need to get reference of the search icon.Any idea how it can be done.
Thanks
BrowseFragment class accesses search icon using title view's getSearchAffordanceView()
private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
new BrowseFrameLayout.OnFocusSearchListener() {
#Override
public View onFocusSearch(View focused, int direction) {
// If headers fragment is disabled, just return null.
if (!mCanShowHeaders) return null;
final View searchOrbView = mTitleView.getSearchAffordanceView();
.
.
.
Since mTitleView is BrowseFragment's private member, you cannot get search icon reference directly. The only properties you can control for search affordance in the fragment title are: visibility and color. Visibility is controlled by the presence of a search listener.

How can I bind a UITableViewCell's subview event to a view model ICommand?

I have a view that uses several MonoTouch.Dialog elements for screen controls. I've been able to create fluent bindings for all of the screen controls except one, a ButtonElement, because I can't access the TouchUpInside event of its UIButton subview.
Here's the pseudocode that creates the controls, builds the screen, and creates the bindings.
// Controls created
CheckboxElement checkbox = new CheckboxElement("Lorem ipsum dolor");
StringElement string1 = new StringElement("Sit amet");
StringElement string2 = new StringElement("Consectetur");
ButtonElement button = new ButtonElement("Adipiscing", delegate{method();});
// Elements used to create view
List<Element> elements = new List<Element>(){checkbox, string1, string2, button};
AddElements(elements);
// Bind controls to view model properties
var set = this.CreateBindingSet<SettingsView, SettingsViewModel>();
set.Bind(checkbox).For(v => v.BooleanValue).To(vm => vm.CheckboxProperty).TwoWay();
set.Bind(string1).For(v => v.Value).To(vm => vm.String1Property);
set.Bind(string2).For(v => v.Value).To(vm => vm.String2Property);
// Binding to ButtonElement TouchUpInside event would go here
set.Apply();
The ButtonElement that has a UIButton as its only subview and it is this subview's TouchUpInside event that I want to link to an ICommand method in the view model.
public ICommand TouchUpInsideCommand()
{
get { ... }
}
Right now in ButtonElement, when the UIButton is created in GetCell, its TouchUpInside event is linked to the anonymous delegate method that's passed in as part of ButtonElement's constructor and stored in an NSAction called Tapped.
button.TouchUpInside += (o, e) => Tapped.Invoke();
To remove this event handling I've created a new class called ButtonElementMvx that inherits from ButtonElement. In ButtonElementMvx's GetCell method I remove the event handling that was set up by its parent .
public ButtonElementMvx : ButtonElement
{
...
public override UITableViewCell GetCell(UITableView tv)
{
UITableViewCell cell = base.GetCell(tv);
button.TouchUpInside -= ButtonTouchUpInsideEventHandler;
return cell;
}
}
ButtonTouchUpInsideEventHandler is a reference to the anonymous delegate method created in ButtonElement's GetCell (I know this implementation might be a bit kludgy but I'll clean it up later).
Here's my question - What is the best way to create a binding to the ButtonElement's UIButton TouchUpInside event inside my view where I'm creating my other bindings?
buttonElement : ButtonElement
|
-> uiButton : UIButton
|
-> TouchUpInside
Something along the lines of
set.Bind(buttonElement.uiButton).For("TouchUpInside").To(vm => vm.TouchUpInsideCommand);
I've done some research and I think the way forward is to create a custom binding that is added to the registry on startup (outlined in Stuart's N=28 - Custom Binding video) as well as extending my ButtonElementMvx class to create a fully bindable UIButton that I can access the button's TouchUpInside event and bind it in my view along with my other controls.
Any thoughts? Is this the correct way to proceed or am I heading off in the wrong direction?

Enable/Disable FINISH button of wizard based on user input

I have created a wizard in AX 2012 using wizard wizard... Now i need to put 1 functionality i.e., to Enable or Disable FINISH button based on user input.
I have already tried these 3 ways but without success..
this.finishenabled() -- on SetupNavigation method of wizard class
finishenabled[formrun.tabidx()] = false -- on SetupNavigation method of wizard class
syswizard.finishenable(false, curtabidx(),false) - on Tabpage of wizard form
please do reply if anyone have a solution for this....
The Wizard class has a validate method in which you will do the following:
boolean validate()
{
if(SomeTestCondition)
{
return true;
}
return false;
}
According to Microsoft, this method does the following:
Used to validate user input, and called before the wizard is closed.
It returns false if user input is invalid. This will prevent the run method from being called when the user clicks the Finish button.
Wizard Class on MSDN
Additionally, you can use the textchanged() method on the field you want to validate (or if not text, you can use the changed method of the object).
if (this.text())
{
if (!sysWizard.isNextEnabled())
{
sysWizard.nextEnabled(true, sysWizard.curTab(), false);
}
}
else
{
if (sysWizard.isNextEnabled())
sysWizard.nextEnabled(false, sysWizard.curTab(), false);
}
Also from MSDN Enable Buttons
In SysWizard class the check to enable / disable the finishButton is inside a check for this.hasFinishButton() (see SysWizard.enableButtons).
I overcame this issue by overwriting the hasFinishButton() method on your wizard class and set the ret = true. This does mean however that your finish buttons will show in all steps, but you can hide this with other code if necessary.
The simplest way to enable/disable the Finish button on a Wizard form called from a SysWizard class is to retrieve the FormControl object from the FormRun object using the FormControlId and then set the Enabled property based on the your test condition, such as whether another FormControl contains a value. There are many ways to implement this. I'll provide two examples.
In the first example, all of the modifications are done on the Wizard Form.
A FormControl is used that can be called like any FormControl that has the AutoDeclaration property set to Yes.
In the second example, I'll override the finishEnabled() method on my Wizard class, so it behaves in the manner that was expected.
In each example, the formControl is found using the FormControlId which takes the control's label text ("Finish") as the argument. I found the correct Label ID by doing a "Lookup Label/Text" on "Finish" in the code editor and then selected the SYS label with "Label for Finish button in wizard" in the label's Description.
Example 1: FormControl object on Wizard Form:
In the Form classDeclaration add the following:
class FormRun extends ObjectRun
{
//FormControl objects used to get SysWizard Finish Button
FormControlId finishButtonId;
FormControl finishButton;
}
Initialize the new FormControl in the top level Form init() method:
void init()
{
super();
if (element.Args().caller())
{
sysWizard = element.Args().caller();
}
finishButtonId = sysWizard.formRun().controlId("#SYS302811");
finishButton = sysWizard.formRun().control(finishButtonId);
finishButton.enabled(false);
}
Now you can use the control like you would any other form control. In this case, I'm using the state of checkbox control named IsFinished in my WizardForm as the test condition and updating the FormControl state from the IsFinished.clicked() method:
public void clicked()
{
super();
//set FormControl state based on the current value of the checkbox
finishButton.enabled(this.checked());
}
*Example 2:*Override the finishEnabled() method in your Wizard class:
Note that you'll need to set the default values for the method parameters otherwise AX will throw a compile error because it doesn't match the signature from the base class. For some reason, AX doesn't properly create the method signature. Get rid of the default call to super and replace it with the code below:
public boolean finishEnabled(boolean _enabled = false,
int _idx = this.curTab(),
boolean _setfocus = false)
{
return this.formRun().control(this.formRun().controlId("#SYS302811")).enabled(_enabled);
}
Initialize the control value in the Form init() method:
void init()
{
super();
if (element.Args().caller())
{
sysWizard = element.Args().caller();
}
sysWizard.finishEnabled();
}
Call the class method when your controls are updated:
public void clicked()
{
super();
//set FormControl state based on the current value of the checkbox
sysWizard.finishEnabled(this.checked());
}

How to add skip button to ASP.NET Wizard?

I know how can I skip steps programmatically but I need "Skip" button too.
If you wish to add a new button to the wizard control then you will need to replace the existing Templates by creating custom
WizardStepNavigationTemplates(this is the template which is responsible for the controls which are displayed when on any normal wizard step)
WizardStartNavigationTemplate(this is the template which is responsible for the controls which are displayed when on the FIRST step of the wizard) and
WizardFinishNavigationTemplate (this is the template which is responsible for the controls which are displayed when on the Last step of the wizard)
internal class CustomWizardStartNavigationTemplate : CustomWizardNavigationTemplateBase
{
#region ITemplate Members
public CustomWizardStartNavigationTemplate(WizardDisplayConfig wizardDisplayConfig):base(wizardDisplayConfig){ }
/// <summary>
/// this overrides the method to define the navigation controls which will appear in the template.
/// Literal control is used to put spacing between the controls.
/// </summary>
public override void InstantiateIn(Control container)
{
Literal spacingliteral = new Literal();
spacingliteral.Text += "&nbsp;";
Button btnSkip = new Button();
Button btnSave= new Button();
Button btnNext= new Button();
container.Controls.Add(btnSave);
container.Controls.Add(spacingliteral);
container.Controls.Add(btnNext);
container.Controls.Add(spacingliteral);
container.Controls.Add(btnSkip);
}
#endregion
}
Something like below is a sample implementation of how you can achieve the desired results. Note that by creating these new templates you will need to add button click events etc which i have not shown in my example. This is so when user clicks the button they will be moved to the next step etc.Hope this helps.
cheers
Niall

Resources