This tip shows how to create custom state machine workflow using Visual Studio with the step by step snippets of it. It is useful because it covers the basics of state machine workflow and how it configures. This tip will also help to configure the properties of each activity and its methods.
When workflow starts, it assigns the task to the originator of workflow. When workflow task percentage completes set to 100% it goes to the next state (second task). You can see the second task in the task list. In the second task, if you are not setting the percentage complete 100% the workflow goes back to the first state (first task), otherwise it is in finalize state.
Follow these Steps
- Create new state machine workflow project or Add state machine workflow item into existing project.
- It automatically creates
WorkflowInitialstate state in it.
- In this event driven activity
onworkflowactivated is automatically created.
setStateActivity in it for the purpose of calling another state.
Add state from tools on design and bind it to
InitialState. After setting the
TargetStateName, you can see the link between them.
- First Task:
eventdrivenactivity to the state (First Task).
In stateInitializationActivity of first task, set the createtask activity in it.
Set the properties of
- Create its new
correlationToken(FirstTaskToken) and set its
owneractivityname as its state (First Task)
- Create its
In eventdrivenactivity, set ontaskchanged activity in it.
- Create its after properties.
Ifelse activity on design.
on left part (if). If required set
- set properties of
setStateActivity targetStateName as another state(
HistoryDescription for record history.
- Set the code condition of
- Second Task:
Perform the same activity as the first task. And set its
setStateActivity targetStateName as
Here, the only change is that set extra
else part (right side) for state change to any other state (Here workflow switches to
- Final Task:
- Drag one state to design.
- Set it as final activity by choosing the "Set as complete state". See the below image.
- Finally workflow looks like:
The code is as follows:
public sealed partial class StateMachineWorkflow : StateMachineWorkflowActivity
public SPWorkflowActivationProperties workflowProperties =
public Guid createTask1_TaskId = default(System.Guid);
public SPWorkflowTaskProperties createTask1_TaskProperties =
public SPWorkflowTaskProperties onTaskChanged1_AfterProperties =
private void createTask1_MethodInvoking(object sender, EventArgs e)
createTask1_TaskId = Guid.NewGuid();
createTask1_TaskProperties.Title = "First Task";
createTask1_TaskProperties.PercentComplete = 0f;
createTask1_TaskProperties.Description = "This is the first task
created after its percentage 100% done workflow goes to second state.";
createTask1_TaskProperties.AssignedTo = workflowProperties.OriginatorUser.LoginName;
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
onTaskChanged1_AfterProperties = onTaskChanged1.AfterProperties;
private void FirstTaskCondition(object sender, ConditionalEventArgs e)
if (onTaskChanged1_AfterProperties.PercentComplete == 1.0)
e.Result = true;
e.Result = false;
public Guid createTask2_TaskId = default(System.Guid);
public SPWorkflowTaskProperties createTask2_TaskProperties =
public SPWorkflowTaskProperties onTaskChanged2_AfterProperties =
private void createTask2_MethodInvoking(object sender, EventArgs e)
createTask2_TaskId = Guid.NewGuid();
createTask2_TaskProperties.Title = "Second Task";
createTask2_TaskProperties.PercentComplete = 0f;
createTask2_TaskProperties.Description = "This is the second task
created after its percentage 100% done workflow goes to
final state otherwise back to first task state.";
createTask2_TaskProperties.AssignedTo = workflowProperties.OriginatorUser.LoginName;
private void onTaskChanged2_Invoked(object sender, ExternalDataEventArgs e)
onTaskChanged2_AfterProperties = onTaskChanged2.AfterProperties;
private void SecondTaskCondition(object sender, ConditionalEventArgs e)
if (onTaskChanged2_AfterProperties.PercentComplete == 1.0)
e.Result = true;
e.Result = false;