商信互联
XAF随调度程序模块一起提供。此模块用于通过专门设计用于显示和管理计划信息的控件来显示IEvent对象的列表视图。在某些情况下,有必要创建一个实现IEvent接口的自定义类和一个额外的ISupportReccurrence接口,以启用调度程序对重复事件的支持。在这种情况下,要注意一个特殊之处。创建异常事件时,您可能会注意到IEvent中未定义的其他属性界面,失去价值。在本主题中,我们将在一个示例中对此进行说明,解释其发生的原因,并提供针对此问题的解决方案。
移动应用程序不支持调度程序模块,因此本主题中描述的方法无法在移动平台中实现。
可在http://www.devexpress.com/example=E1088的DevExpress代码示例数据库中找到完整的示例项目。
为了说明问题,我们有一个XAF应用程序解决方案,其中包含ExtendedEvent类的定义。这个类实现了IEvent和ISupportReccurrence接口,并且在没有定义额外的公共财产IEvent界面-注释属性。我们可以从头开始实现ExtendedEvent类,但是为了简单起见,它是从Event类继承的。
[DefaultClassOptions]
public class ExtendedEvent : Event {
public ExtendedEvent(Session session) : base(session) { }
public string Notes {
get { return GetPropertyValue<string>(nameof(Notes)); }
set { SetPropertyValue<string>(nameof(Notes), value); }
}
}
<DefaultClassOptions> _
Public Class ExtendedEvent
Inherits DevExpress.Persistent.BaseImpl.Event
Public Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
Public Property Notes() As String
Get
Return GetPropertyValue(Of String)(NameOf(Notes))
End Get
Set(ByVal value As String)
SetPropertyValue(Of String)(NameOf(Notes), value)
End Set
End Property
End Class
让我们创建一个定期活动,该活动代表每周一次的会议,该会议从上午10点开始,并将其Notes属性设置为“常规会议”:
现在,让我们更改事件的发生时间,这样就可以提前一个小时开始-上午9点。为此,我们可以双击事件并选择“编辑此事件”,也可以在调度程序的时间轴上拖动事件矩形。现在,选择无关紧要,因此我们只需拖动它即可。
注意事件发生的象形图是如何交叉的。这表明事件的发生不再与“重复发生模式”中定义的设置匹配。因此,它存储在异常的集合中。现在,让我们打开事件以检查我们在ExtendedEvent类中引入的其他Notes属性。
如您所见,Notes属性的值为空。创建异常事件时,调度程序仅考虑IEvent接口中定义的属性。在下面的代码片段中,我们说明了如何通过处理SchedulerListEditorBase.ExceptionEventCreated事件来解决此问题。创建异常事件时,将发生此事件。事件处理程序的参数提供两个属性。
在最简单的情况下,当其他属性不需要自定义处理时,您需要将其他属性的值从PatternEvent返回的对象复制到ExceptionEvent属性返回的对象。以下代码段说明了如何通过视图控制器执行此操作。
using DevExpress.ExpressApp.Scheduler;
//...
public partial class CustomEventController : ViewController {
private SchedulerListEditorBase schedulerEditor;
public CustomEventController() {
InitializeComponent();
this.TargetViewType = ViewType.ListView;
}
private void CustomEventController_Activated(object sender, EventArgs e) {
schedulerEditor = ((ListView)View).Editor as SchedulerListEditorBase;
if (schedulerEditor != null) {
schedulerEditor.ExceptionEventCreated =
new EventHandler<ExceptionEventCreatedEventArgs>(
schedulerEditor_ExceptionEventCreated);
}
}
private void CustomEventController_Deactivating(object sender, EventArgs e) {
if (schedulerEditor != null) {
schedulerEditor.ExceptionEventCreated -=
new EventHandler<ExceptionEventCreatedEventArgs>(
schedulerEditor_ExceptionEventCreated);
}
}
void schedulerEditor_ExceptionEventCreated(object sender, ExceptionEventCreatedEventArgs e) {
if (e.PatternEvent is ExtendedEvent && e.ExceptionEvent is ExtendedEvent) {
((ExtendedEvent)e.ExceptionEvent).Notes = ((ExtendedEvent)e.PatternEvent).Notes;
}
}
}
Partial Public Class CustomEventController
Inherits ViewController
Private schedulerEditor As SchedulerListEditorBase
Public Sub New()
InitializeComponent()
Me.TargetViewType = ViewType.ListView
End Sub
Private Sub CustomEventController_Activated(ByVal sender As Object, ByVal e As EventArgs) _
Handles MyBase.Activated
schedulerEditor = TryCast((CType(View, ListView)).Editor, SchedulerListEditorBase)
If schedulerEditor IsNot Nothing Then
AddHandler schedulerEditor.ExceptionEventCreated, AddressOf _
schedulerEditor_ExceptionEventCreated
End If
End Sub
Private Sub CustomEventController_Deactivating(ByVal sender As Object, ByVal e As EventArgs) _
Handles MyBase.Deactivating
If schedulerEditor IsNot Nothing Then
RemoveHandler schedulerEditor.ExceptionEventCreated, _
AddressOf schedulerEditor_ExceptionEventCreated
End If
End Sub
Private Sub schedulerEditor_ExceptionEventCreated(ByVal sender As Object, _
ByVal e As ExceptionEventCreatedEventArgs)
If TypeOf e.PatternEvent Is ExtendedEvent AndAlso TypeOf e.ExceptionEvent Is _
ExtendedEvent Then
CType(e.ExceptionEvent, ExtendedEvent).Notes = (CType( _
e.PatternEvent, ExtendedEvent)).Notes
End If
End Sub
End Class
当CustomEventController被激活时,它会检查当前列表视图的是否列表编辑器从导出SchedulerListEditorBase与否。如果是,则Controller订阅SchedulerListEditorBase.ExceptionEventCreated事件。在事件处理程序中,控制器检查是否为ExtendedEvent类激活了计划程序。如果是,则Controller将Notes属性的值复制到创建的例外事件发生处。停用控制器后,它将取消订阅ExceptionEventCreated事件。
现在,如果我们创建一个重复事件并更改其发生,Notes属性将保留其原始值。
请注意,您无法使用标准的“保存”验证上下文使用验证规则来装饰通过ExceptionEventCreated事件处理的其他属性。引发IObjectSpace.Committing事件时,将检查此上下文。但是,引发IObjectSpace.ObjectSaving事件时,属性值将复制到异常事件发生处。在ObjectSaving事件之前引发Committing事件,因此在将正确的值分配给相应的属性之前检查此类验证规则。在这种情况下,请使用自定义验证上下文,而不是标准的Save上下文。
using DevExpress.ExpressApp.Xpo;
using DevExpress.ExpressApp.Validation;
// ...
public class ExtendedEvent : Event {
[RuleRequiredField("", "SchedulerValidation")]
public string Notes {
// ...
protected override void OnSaving() {
base.OnSaving();
Validator.RuleSet.Validate(XPObjectSpace.FindObjectSpaceByObject(this), this, "SchedulerValidation");
}
}
Imports DevExpress.ExpressApp.Xpo
Imports DevExpress.ExpressApp.Validation
' ...
Public Class ExtendedEvent
Inherits Event
<RuleRequiredField("", "SchedulerValidation")> _
Public ReadOnly Property Notes() As String
' ...
Protected Overrides Sub OnSaving()
MyBase.OnSaving()
Validator.RuleSet.Validate(XPObjectSpace.FindObjectSpaceByObject(Me), Me, "SchedulerValidation")
End Sub
End Class
当其他事件属性填充值时,触发验证也很有意义。
using DevExpress.ExpressApp.Validation;
// ...
void schedulerEditor_ExceptionEventCreated(object sender, ExceptionEventCreatedEventArgs e) {
if (e.PatternEvent is ExtendedEvent && e.ExceptionEvent is ExtendedEvent) {
((ExtendedEvent)e.ExceptionEvent).Notes = ((ExtendedEvent)e.PatternEvent).Notes;
Validator.RuleSet.Validate(ObjectSpace, e.ExceptionEvent, "SchedulerValidation");
}
}
Imports DevExpress.ExpressApp.Validation
'...
Private Sub schedulerEditor_ExceptionEventCreated(ByVal sender As Object, _
ByVal e As ExceptionEventCreatedEventArgs)
If TypeOf e.PatternEvent Is ExtendedEvent AndAlso TypeOf e.ExceptionEvent Is ExtendedEvent Then
CType(e.ExceptionEvent, ExtendedEvent).Notes = (CType(e.PatternEvent, ExtendedEvent)).Notes
Validator.RuleSet.Validate(ObjectSpace, e.ExceptionEvent, "SchedulerValidation")
End If
End Sub