Predefined State Transitions Created in Code (在代码中创建的预定义状态转换)
This topic describes how to create a predefined State Machine in code. A predefined State Machine cannot be changed by users. For information how to define a state machine at runtime, refer to the User-Defined State Transitions Specified at Runtime topic instead.
本主题介绍如何在代码中创建预定义状态机。预定义状态机不能被用户修改。有关如何在运行时定义状态机的信息,请参阅“运行时指定的用户定义状态转换”主题。
**Important **
In certain scenarios, creating a custom Controller with the SingleChoiceAction Action or a set of SimpleAction Actions can be simpler and more straightforward than defining a coded State Machine. So, if you need to define a static state management process that should not be changed by users, consider this approach first instead of using the State Machine module.
在某些场景中,使用SingleChoiceAction动作或一组SimpleAction动作创建自定义控制器,可能比定义编码状态机更简单直接。因此,若需定义一个不应被用户修改的静态状态管理流程,建议优先考虑此方法,而非使用状态机模块。
See Also:
另请参见:
Add a Simple Action
添加简单动作
Add a Parametrized Action
添加参数化动作
How to: Include an Action to a Detail View Layout
如何:将动作包含到详情视图布局中
Note
To see this example in action, refer to the State Machine section of the Feature Center demo located in the %PUBLIC%\Documents\DevExpress Demos 24.1\Components\XAF\FeatureCenter.NETFramework.XPO folder by default, or refer to the Feature Center demo online.
要查看实际运行的示例,请参考Feature Center演示中的“状态机”部分,其默认位于%PUBLIC%\Documents\DevExpress Demos 24.1\Components\XAF\FeatureCenter.NETFramework.XPO文件夹,或在线参考Feature Center演示。
The following code defines a simple Task business class, which can have different states such as not started, in progress, completed, etc.
以下代码定义了一个简单的Task业务类,它可以具有不同的状态,如未开始、进行中、已完成等。
C# (EF Core)
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
using System.ComponentModel.DataAnnotations;
//...
public enum TaskStatus { Draft, NotStarted, InProgress, Paused, Completed, Dropped }
[DefaultClassOptions,ImageName("BO_Task")]
public class Task : BaseObject {
public virtual string Subject { get; set; }
public virtual TaskStatus Status { get; set; }
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
C# (XPO)
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Xpo;
//...
public enum TaskStatus { Draft, NotStarted, InProgress, Paused, Completed, Dropped }
[DefaultClassOptions, ImageName("BO_Task")]
public class Task : BaseObject {
public Task(Session session) : base(session) { }
public string Subject {
get { return GetPropertyValue<string>(nameof(Subject)); }
set { SetPropertyValue<string>(nameof(Subject), value); }
}
public TaskStatus Status {
get { return GetPropertyValue<TaskStatus>(nameof(Status)); }
set { SetPropertyValue<TaskStatus>(nameof(Status), value); }
}
}
To create a state machine for this class, perform the following steps.
要为此类创建状态机,请执行以下步骤。
1.Declare a StateMachine<T> class descendant with the generic type parameter specifying the target business class. Override the Name property to specify a textual description for a state machine.
声明一个StateMachine<T>类的派生类,其泛型类型参数指定目标业务类。重写Name属性以指定状态机的文本描述。
C#
using DevExpress.ExpressApp.StateMachine.NonPersistent;
//...
public class TaskStatusStateMachine : StateMachine<Task> {
public override string Name {
get { return "Change status to"; }
}
}
2.Decide which business class property should be used as a state property. To function, a state machine must be able to distinguish between object states. This is why you need to specify a property whose values will represent different object states. This can be either an enumeration-typed property or a reference property. In this example, the Status property is a perfect candidate. Thus, it is used as a state property, and consequently, its values will be used as state markers. Note that different states must use different marker objects. To specify a state property, override the StatePropertyName property.
确定应将业务类的哪个属性用作状态属性。状态机要正常工作,必须能够区分对象的不同状态。因此,需要指定一个属性,其值将表示对象的不同状态。该属性可以是枚举类型属性或引用属性。在本示例中,Status属性是理想选择。因此,它被用作状态属性,其值将作为状态标记。注意,不同的状态必须使用不同的标记对象。要指定状态属性,请重写StatePropertyName属性。
C#
public class TaskStatusStateMachine : StateMachine<Task> {
//...
public override string StatePropertyName {
get { return "Status"; }
}
}
3.Declare a set of allowed states and transitions between them. States are State class instances and transitions are Transition class instances. A state belongs to a state machine and has an associated caption and a marker. Each state has a collection of allowed transitions that specify possible target states. In this example, it should not be possible for a task to become completed until it is in progress, so the in progress state should not contain a completed transition.
声明一组允许的状态以及它们之间的转换。状态是State类的实例,转换是Transition类的实例。一个状态属于一个状态机,并具有关联的标题和标记。每个状态都有一个允许的转换集合,用于指定可能的目标状态。在本示例中,任务在进行中之前不能变为已完成状态,因此进行中状态不应包含到已完成状态的转换。
C#
using DevExpress.ExpressApp.StateMachine;
//...
public class TaskStatusStateMachine : StateMachine<Task> {
//...
private IState startState;
public TaskStatusStateMachine(IObjectSpace objectSpace) : base(objectSpace) {
startState = new State(this, TaskStatus.Draft);
IState notStartedState = new State(this, "Not Started", TaskStatus.NotStarted);
IState inProgressState = new State(this, "In Progress", TaskStatus.InProgress);
IState pausedState = new State(this, TaskStatus.Paused);
IState completedState = new State(this, TaskStatus.Completed);
IState droppedState = new State(this, TaskStatus.Dropped);
startState.Transitions.Add(new Transition(notStartedState));
notStartedState.Transitions.Add(new Transition(startState));
notStartedState.Transitions.Add(new Transition(inProgressState));
inProgressState.Transitions.Add(new Transition(pausedState));
inProgressState.Transitions.Add(new Transition(completedState));
inProgressState.Transitions.Add(new Transition(droppedState));
pausedState.Transitions.Add(new Transition(inProgressState));
droppedState.Transitions.Add(new Transition(notStartedState));
States.Add(startState);
States.Add(notStartedState);
States.Add(inProgressState);
States.Add(pausedState);
States.Add(completedState);
States.Add(droppedState);
}
public override IState StartState {
get { return startState; }
}
}
After you have defined states, transitions, and appearance rules in a state machine constructor, add them to the machine’s States collection. Override the StartState property to specify the initial state for newly created objects.
在状态机构造函数中定义状态、转换和外观规则后,将它们添加到状态机的States集合中。重写StartState属性以指定新创建对象的初始状态。
4.A state machine can optionally have Conditional Appearance rules associated with its states. These rules are represented by StateAppearance instances.
状态机可以选择性地为其状态关联条件外观规则。这些规则由StateAppearance实例表示。
C#
public class TaskStatusStateMachine : StateMachine<Task> {
//...
public TaskStatusStateMachine(IObjectSpace objectSpace) : base(objectSpace) {
//...
StateAppearance inProgressAppearance = new StateAppearance(inProgressState);
inProgressAppearance.TargetItems = "Subject";
inProgressAppearance.Enabled = false;
StateAppearance completedAppearance = new StateAppearance(completedState);
completedAppearance.TargetItems = "Subject";
completedAppearance.Enabled = false;
StateAppearance pausedAppearance = new StateAppearance(pausedState);
pausedAppearance.TargetItems = "*";
pausedAppearance.BackColor = System.Drawing.Color.Yellow;
}
}
5.Implement the IStateMachineProvider interface in the target business class. The interface’s only member - GetStateMachines method - returns a list of all state machines available for the business class.
在目标业务类中实现IStateMachineProvider接口。该接口的唯一成员——GetStateMachines方法——返回该业务类可用的所有状态机的列表。
C# (EF Core)
using System.Collections.Generic;
using DevExpress.ExpressApp.EFCore;
using DevExpress.ExpressApp.StateMachine;
using DevExpress.ExpressApp.EFCore;
//...
public class Task : BaseObject, IStateMachineProvider {
//...
public IList<IStateMachine> GetStateMachines() {
List<IStateMachine> result = new List<IStateMachine>();
result.Add(new TaskStatusStateMachine(EFCoreObjectSpace.FindObjectSpaceByObject(this)));
return result;
}
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
C# (XPO)
using System.Collections.Generic;
//...
public class Task : BaseObject, IStateMachineProvider {
//...
public IList<IStateMachine> GetStateMachines() {
List<IStateMachine> result = new List<IStateMachine>();
result.Add(new TaskStatusStateMachine(XPObjectSpace.FindObjectSpaceByObject(this)));
return result;
}
}
The State Machine module will display the ChangeStateAction Action in Task Views. The Action is provided by the StateMachineController.
状态机模块将在Task视图中显示ChangeStateAction动作。该动作由StateMachineController提供。

*Note
The StateMachineController is not designed to execute additional logic using its TransitionExecuting and TransitionExecuted events. Instead, place your custom code in the setter of the desired business class property. *
StateMachineController并非设计为使用其TransitionExecuting和TransitionExecuted事件执行额外逻辑。相反,请将自定义代码放在所需业务类属性的setter中。
You can optionally implement the IStateMachineUISettings interface and set its ExpandActionsInDetailView property to true.
您可以选择性地实现IStateMachineUISettings接口,并将其ExpandActionsInDetailView属性设置为true。
C#
public class TaskStatusStateMachine : StateMachine<Task>, IStateMachineUISettings {
//...
public bool ExpandActionsInDetailView {
get { return true; }
}
}
In this instance, the target business class Detail Views will contain separate Simple Actions corresponding to available state transitions.
在这种情况下,目标业务类的详情视图将包含与可用状态转换对应的独立Simple Actions。

1248

被折叠的 条评论
为什么被折叠?



