自定义删除行为
删除元素通常导致相关元素也将被删除。任何关系连接到它,因此,所有子元素被删除。此行为名为 删除发送。您可以自定义删除发送,如封送处理的其他相关删除组件。通过编写程序代码,可以进行 delete 发送取决于模型的状态。还可以导致其他更改在响应删除。
本主题包括下列章节:
删除默认行为
设置传播删除角色的选项
重写删除关闭 –使用删除可能导致相邻元素的删除的此方法。
使用 OnDeleting 和 OnDeleted –使用在中响应还可以包括其他事件 (如更新一个值或在存储外的这些方法。
删除规则 –使用规则传播任何存储区中的类型更新,以更改可能导致其他。
删除事件 –用于存储事件在存储外传播更新,如用于其他 Visual Studio 文档。
UnMerge –使用 UnMerge 操作取消附加子元素对其父的合并操作。
删除默认行为
默认情况下,下列规则管理删除发送:
如果删除组件,所有嵌入元素也将被删除。嵌入组件是嵌入关系的目标此元素是源的类型。例如,因此,如果有一个嵌入的关系从相册到一个,然后,在特定相册中删除,其所有歌曲也将被删除。
相反,删除一个不删除相册。
默认情况下,删除不会传播引用关系。如果有一个引用关系 ArtistPlaysOnAlbum 从相册到艺术家,删除相册不删除任何相关艺术家,并且,删除艺术家不删除任何相册。
但是,删除沿某些内置关系传播。例如,那么,当一个模型元素中移除时,其关系图上的形状也将被删除。元素和形状由 PresentationViewsSubject 相关引用关系。
连接到元素,在源或目标角色的每个关系,删除。元素的角色特性在相反的角色的不再包含已删除的元素。
设置传播删除角色的选项
可以使删除传播沿一个引用关系,或者从嵌入的子级到其父级。
设置删除发送
在 DSL 定义关系图,选择要发送删除的 角色 。该角色。在域关系框的左侧或右侧的行表示。
例如,因此,如果要指定,只要相册中删除,相关艺术家也将被删除,然后选择角色与相关到域类艺术家。
在 " 属性 " 窗口中,将 传播删除 属性。
按 F5 并确认:
在此关系实例中删除,在选定的角色的元素也将被删除。
当在相反的角色的元素中删除,则此关系实例将被删除,并且,此角色的相关元素将被删除。
您还可以查看在 DSL 详细信息 窗口的 传播删除 选项。选择域类,因此,在 DSL 详细信息 " 窗口中,通过单击按钮打开 删除行为 页在窗口一侧。传播 选项为每个关系的对方角色的显示。删除样式 列中指示 传播 选项是否在设置其默认设置,但是,它没有任何单独的效果。
使用程序代码,删除发送
在 DSL 定义文件的选项仅允许您选择删除是否传播到一个即时空间量。若要实现删除发送一个更复杂的模式,可以编写程序代码。
说明 |
---|
若要将程序代码添加到 DSL 定义,请创建一个单独的代码文件。 Dsl 项目和写入部分定义扩充在生成的代码文件夹的类。有关更多信息,请参见 编写代码以自定义域特定语言。 |
定义删除关闭
删除操作使用类 TheModelDeleteClosure 确定删除的哪些元素在给定初始选择。它重复调用 ShouldVisitRelationship() 和 ShouldVisitRolePlayer() ,遍历关系关系图。您可以重写这些方法。ShouldVisitRolePlayer 提供一个链接和元素的标识一致链接的角色。它应返回下列值之一:
VisitorFilterResult.Yes–应删除元素,并且该器应继续尝试组件的其他链接。
VisitorFilterResult.DoNotCare –不应删除元素,除非另一个查询的答复应删除它。
VisitorFilterResult.Never –无法删除元素,因此,即使另一个查询响应 Yes,因此,该器不应尝试组件的其他链接。
// When a musician is deleted, delete their albums with a low rating.
// Override methods in <YourDsl>DeleteClosure in DomainModel.cs
partial class MusicLibDeleteClosure
{
public override VisitorFilterResult ShouldVisitRolePlayer
(ElementWalker walker, ModelElement sourceElement, ElementLink elementLink,
DomainRoleInfo targetDomainRole, ModelElement targetRolePlayer)
{
ArtistAppearsInAlbum link = elementLink as ArtistAppearsInAlbum;
if (link != null
&& targetDomainRole.RolePlayer.Id == Album.DomainClassId)
{
// Count other unvisited links to the Album of this link.
if (ArtistAppearsInAlbum.GetLinksToArtists(link.Album)
.Where(linkAlbumArtist =>
linkAlbumArtist != link &&
!walker.Visited(linkAlbumArtist))
.Count() == 0)
{
// Should delete this role player:
return VisitorFilterResult.Yes;
}
else
// Don’t delete unless another relationship deletes it:
return VisitorFilterResult.DoNotCare;
}
else
{
// Test for and respond to other relationships and roles here.
// Not the relationship or role we’re interested in.
return base.ShouldVisitRolePlayer(walker, sourceElement,
elementLink, targetDomainRole, targetRolePlayer);
}
}
}
关闭技术确保要删除的组元素和链接确定的,则在删除开始之前。该器还将关闭的结果与从模型的其他部分。
但是,该技术,假设删除只影响其关系关系图的邻近生命线:不能使用此方法删除该模型的另一部分的元素。,如果要添加元素或进行其他更改以响应删除,不能使用它。
使用 OnDeleting 和 OnDeleted
您可以重写 OnDeleting() 或 OnDeleted() 在域类,或者在域关系。
OnDeleting 调用,当元素将被删除,时,但是,在其关系已断开连接之前。到或从其他元素可沿,仍在 store.ElementDirectory。
如果多个元素同时删除, OnDeleting 为所有调用执行删除操作之前。
IsDeleting 为 true。
,当元素已删除时,OnDeleted 调用。它在 CLR 堆上保持,以便可以撤消如果必须执行,但是,它与其他组件将展开并从 store.ElementDirectory中移除。对关系,角色仍会引用旧角色扮演者。IsDeleted 为 true。
OnDeleting 和 OnDeleted 调用,当用户调用在创建元素之后时取消,并在早期的删除重复时重做操作。使用 this.Store.InUndoRedoOrRollback 避免在这些情况下更新存储元素。有关更多信息,请参见 如何:使用事务更新模型。
例如,那么,当其最后一个子删除过程,下面的代码中删除相册:
// Delete the parent Album when the last Song is deleted.
// Override methods in the embedding relationship between Album and Song:
partial class AlbumHasSongs
{
protected override void OnDeleted()
{
base.OnDeleted();
// Don't perform in-store actions in undo:
if (this.Store.InUndoRedoOrRollback) return;
// Relationship source and target still work:
// Don't bother if source is already on its way out:
if (!this.Album.IsDeleting && !this.Album.IsDeleted)
{
if (this.Album.Songs.Count == 0)
{
this.Album.Delete();
} } } }
从该关系中删除触发比角色元素通常很有用,因为工作,这两个,当元素中移除时,属性,并且,当该关系删除过程。但是,对于引用关系,您可能要将删除,当一个相关删除组件时,但是,如果没有,该关系删除过程。此示例删除相册,当其最后位提供的艺术家删除过程,但是,它不响应,如果删除关系:
using System.Linq; ...
// Assumes a many-many reference relationship
// between Artist and Album.
partial class Artist
{
protected override void OnDeleting()
{
base.OnDeleting();
if (this.Store.InUndoRedoOrRollback) return;
List<Album> toDelete = new List<Album>();
foreach (Album album in this.Albums)
{
if (album.Artists.Where(artist => !artist.IsDeleting)
.Count() == 0)
{
toDelete.Add(album);
}
}
foreach (Album album in toDelete)
{
album.Delete();
} } }
当您对元素的 Delete , OnDeleting 和 OnDeleted 将调用。即这些方法始终执行内联 ),前面直接和在实际删除后引发其事件。如果代码删除两个或多个元素, OnDeleting 和 OnDeleted 在所有的替换将调用和。
删除规则和事件
为 OnDelete 处理程序外,还可以定义删除规则和删除操作。
Deleting 和 Delete 规则仅触发在事务而不是撤消或重做操作。您可以设置要排队的它们执行对该删除执行的事务末尾。删除规则在队列中的所有删除的规则之前总是执行。
使用规则传播存储仅影响元素,包括关系、关系图元素及其特性的更改。通常,已删除的规则用于传播删除,并且,删除规则用于创建替换元素和关系。
有关更多信息,请参见规则在模型内部传播更改。
Deleted 存储事件调用在事务结束时和在取消后调用或重做操作。这样可用于传播删除到存储外的对象 (如文件、数据库项或其他对象在 Visual Studio。
有关更多信息,请参见 事件处理程序在模型外部传播更改。
警告 当删除组件后,可以访问其字段值,则,但不能定位关系链接。但是,因此,如果您在关系的已删除的事件,还可以访问是其角色扮演者的两个元素。因此,因此,如果需要响应模型元素的删除,但希望访问其链接到的元素,该元素关系的可删除事件而不是模型元素的域类。
示例删除规则
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletingRule : DeletingRule
{
public override void ElementDeleting(ElementDeletingEventArgs e)
{
base.ElementDeleting(e);
// ...perform tasks to propagate imminent deletion
}
}
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletedRule : DeleteRule
{
public override void ElementDeleted(ElementDeletedEventArgs e)
{
base.ElementDeleted(e);
// ...perform tasks such as creating new elements
}
}
// The rule must be registered:
public partial class MusicLibDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(AlbumDeletingRule));
types.Add(typeof(AlbumDeletedRule));
// If you add more rules, list them here.
return types.ToArray();
}
}
示例删除的事件
partial class NestedShapesSampleDocData
{
protected override void OnDocumentLoaded(EventArgs e)
{
base.OnDocumentLoaded(e);
DomainRelationshipInfo commentRelationship =
this.Store.DomainDataDirectory
.FindDomainRelationship(typeof(CommentsReferenceComponents));
this.Store.EventManagerDirectory.ElementDeleted.Add(commentRelationship,
new EventHandler<ElementDeletedEventArgs>(CommentLinkDeleted));
}
private void CommentLinkDeleted (object sender, ElementDeletedEventArgs e)
{
CommentsReferenceComponents link = e.ModelElement as CommentsReferenceComponents;
Comment comment = link.Comment;
Component component = link.Subject;
if (comment.IsDeleted)
{
// The link was deleted because the comment was deleted.
System.Windows.Forms.MessageBox.Show("Removed comment on " + component.Name);
}
else
{
// It was just the link that was deleted - the comment itself remains.
System.Windows.Forms.MessageBox.Show("Removed comment link to "
+ component.Name);
}
}
}
UnMerge
附加子元素对其父的操作调用 合并。,当元素的新元素或一组从工具箱创建或从模型的另一部分进行移动或从剪贴板时,复制它发生。并创建父任务和其新的子级之间的一个嵌入的关系,合并操作还可以设置其他关系,创建附属元素,并在组件的属性值。合并操作在元素合并指令 (EMD)中封装。
EMD 还封装添加 unmerge 或 MergeDisconnect 操作。如果使用合并,构造的组件群集,建议使用关联的 unmerge 从中移除元素,因此,如果处于一致的状态若要将其余元素中。unmerge 操作通常会使用上一节中描述的技术。
有关更多信息,请参见 自定义元素创建和移动。