Files
Umbraco-CMS/umbraco/cms/businesslogic/CMSNode.cs
slace eed74f864e DO NOT DOWNLOAD. DOWNLOAD LATEST STABLE FROM RELEASE TAB
support for a full cancelable event model on document

[TFS Changeset #56025]
2009-07-06 12:04:51 +00:00

812 lines
32 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Xml;
using umbraco.cms.businesslogic.index;
using umbraco.cms.businesslogic.web;
using umbraco.DataLayer;
using umbraco.BusinessLogic;
using System.IO;
using System.Text.RegularExpressions;
using System.ComponentModel;
namespace umbraco.cms.businesslogic {
/// <summary>
/// CMSNode class serves as the base class for many of the other components in the cms.businesslogic.xx namespaces.
/// Providing the basic hierarchical data structure and properties Text (name), Creator, Createdate, updatedate etc.
/// which are shared by most umbraco objects.
///
/// The child classes are required to implement an identifier (Guid) which is used as the objecttype identifier, for
/// distinguishing the different types of CMSNodes (ex. Documents/Medias/Stylesheets/documenttypes and so forth).
/// </summary>
public class CMSNode : BusinessLogic.console.IconI {
private string _text;
private int _id = 0;
private Guid _uniqueID;
/// <summary>
/// Private connectionstring
/// </summary>
protected static readonly string _ConnString = GlobalSettings.DbDSN;
private int _parentid;
private Guid _nodeObjectType;
private int _level;
private string _path;
private bool _hasChildren;
private int _sortOrder;
private int _userId;
private DateTime _createDate;
private bool _hasChildrenInitialized;
private string m_image = "default.png";
private static readonly string m_DefaultIconCssFile = GlobalSettings.FullpathToRoot + GlobalSettings.Path + System.IO.Path.DirectorySeparatorChar + "css" + System.IO.Path.DirectorySeparatorChar + "treeIcons.css";
private static List<string> m_DefaultIconClasses = new List<string>();
/// <summary>
/// Gets the default icon classes.
/// </summary>
/// <value>The default icon classes.</value>
public static List<string> DefaultIconClasses {
get {
if (m_DefaultIconClasses.Count == 0)
initializeIconClasses();
return m_DefaultIconClasses;
}
}
private static void initializeIconClasses() {
StreamReader re = File.OpenText(m_DefaultIconCssFile);
string content = string.Empty;
string input = null;
while ((input = re.ReadLine()) != null) {
content += input.Replace("\n", "") + "\n";
}
re.Close();
// parse the classes
MatchCollection m = Regex.Matches(content, "([^{]*){([^}]*)}", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match match in m) {
GroupCollection groups = match.Groups;
string cssClass = groups[1].Value.Replace("\n", "").Replace("\r", "").Trim().Trim(Environment.NewLine.ToCharArray());
m_DefaultIconClasses.Add(cssClass);
}
}
/// <summary>
/// Gets the SQL helper.
/// </summary>
/// <value>The SQL helper.</value>
protected static ISqlHelper SqlHelper {
get { return Application.SqlHelper; }
}
public CMSNode()
{
throw new NotSupportedException();
}
/// <summary>
/// Initializes a new instance of the <see cref="CMSNode"/> class.
/// </summary>
/// <param name="Id">The id.</param>
public CMSNode(int Id) {
_id = Id;
setupNode();
}
/// <summary>
/// Initializes a new instance of the <see cref="CMSNode"/> class.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="noSetup">if set to <c>true</c> [no setup].</param>
public CMSNode(int id, bool noSetup) {
_id = id;
//TODO: add the following as noSetup currenlty doesn't actuall do anything!?? This can't happen until
//inheriting classes can override setupNode instead of using their own implementation (i.e. Document: setupDocument)
//if (!noSetup)
//setupNode();
}
/// <summary>
/// Initializes a new instance of the <see cref="CMSNode"/> class.
/// </summary>
/// <param name="uniqueID">The unique ID.</param>
public CMSNode(Guid uniqueID) {
_id = SqlHelper.ExecuteScalar<int>("SELECT id FROM umbracoNode WHERE uniqueID = @uniqueId", SqlHelper.CreateParameter("@uniqueId", uniqueID));
setupNode();
}
/// <summary>
/// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility
/// </summary>
public virtual void Save() {
SaveEventArgs e = new SaveEventArgs();
this.FireBeforeSave(e);
if (!e.Cancel) {
//In the future there will be SQL stuff happening here...
this.FireAfterSave(e);
}
}
/// <summary>
/// Sets up the internal data of the CMSNode, used by the various constructors
/// </summary>
protected void setupNode() {
IRecordsReader dr = SqlHelper.ExecuteReader(
"SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = " + this.Id
);
bool noRecord = false;
if (dr.Read())
{
// testing purposes only > original umbraco data hasn't any unique values ;)
// And we need to have a parent in order to create a new node ..
// Should automatically add an unique value if no exists (or throw a decent exception)
if (dr.IsNull("uniqueID")) _uniqueID = Guid.NewGuid();
else _uniqueID = dr.GetGuid("uniqueID");
_nodeObjectType = dr.GetGuid("nodeObjectType");
_level = dr.GetShort("level");
_path = dr.GetString("path");
_parentid = dr.GetInt("parentId");
_text = dr.GetString("text");
_sortOrder = dr.GetInt("sortOrder");
_userId = dr.GetInt("nodeUser");
_createDate = dr.GetDateTime("createDate");
}
else
noRecord = true;
dr.Close();
if (noRecord) {
throw new ArgumentException(string.Format("No node exists with id '{0}'", Id));
}
}
/// <summary>
/// Sets up the node for the content tree.
/// </summary>
/// <param name="uniqueID">The unique ID.</param>
/// <param name="nodeObjectType">Type of the node object.</param>
/// <param name="Level">The level.</param>
/// <param name="ParentId">The parent id.</param>
/// <param name="UserId">The user id.</param>
/// <param name="Path">The path.</param>
/// <param name="Text">The text.</param>
/// <param name="CreateDate">The create date.</param>
/// <param name="hasChildren">if set to <c>true</c> [has children].</param>
protected void SetupNodeForTree(Guid uniqueID, Guid nodeObjectType, int Level, int ParentId, int UserId, string Path, string Text,
DateTime CreateDate, bool hasChildren) {
_uniqueID = uniqueID;
_nodeObjectType = nodeObjectType;
_level = Level;
_parentid = ParentId;
_userId = UserId;
_path = Path;
_text = Text;
_createDate = CreateDate;
HasChildren = hasChildren;
}
/// <summary>
/// Gets or sets the sort order.
/// </summary>
/// <value>The sort order.</value>
public int sortOrder {
get { return _sortOrder; }
set {
_sortOrder = value;
SqlHelper.ExecuteNonQuery("update umbracoNode set sortOrder = '" + value + "' where id = " + this.Id.ToString());
}
}
/// <summary>
/// Gets or sets the create date time.
/// </summary>
/// <value>The create date time.</value>
public DateTime CreateDateTime {
get { return _createDate; }
set {
_createDate = value;
SqlHelper.ExecuteNonQuery("update umbracoNode set createDate = @createDate where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@createDate", _createDate));
}
}
/// <summary>
/// Gets the creator
/// </summary>
/// <value>The user.</value>
public BusinessLogic.User User {
get {
return BusinessLogic.User.GetUser(_userId);
}
}
/// <summary>
/// Method for checking if a CMSNode exits with the given Guid
/// </summary>
/// <param name="uniqueID">Identifier</param>
/// <returns>True if there is a CMSNode with the given Guid</returns>
static public bool IsNode(Guid uniqueID) {
return (SqlHelper.ExecuteScalar<int>("select count(id) from umbracoNode where uniqueID = @uniqueID", SqlHelper.CreateParameter("@uniqueId", uniqueID)) > 0);
}
/// <summary>
/// Method for checking if a CMSNode exits with the given id
/// </summary>
/// <param name="Id">Identifier</param>
/// <returns>True if there is a CMSNode with the given id</returns>
static public bool IsNode(int Id) {
return (SqlHelper.ExecuteScalar<int>("select count(id) from umbracoNode where id = '" + Id + "'") > 0);
}
/// <summary>
/// Gets the id.
/// </summary>
/// <value>The id.</value>
public int Id {
get { return _id; }
}
/// <summary>
/// Given the hierarchical tree structure a CMSNode has only one parent but can have many children
/// </summary>
/// <value>The parent.</value>
public CMSNode Parent {
get {
if (Level == 1) throw new ArgumentException("No parent node");
return new CMSNode(_parentid);
}
set {
_parentid = value.Id;
SqlHelper.ExecuteNonQuery("update umbracoNode set parentId = " + value.Id.ToString() + " where id = " + this.Id.ToString());
}
}
#region IconI members
// Unique identifier of the given node
/// <summary>
/// Unique identifier of the CMSNode, used when locating data.
/// </summary>
public Guid UniqueId {
get { return _uniqueID; }
}
/// <summary>
/// Human readable name/label
/// </summary>
public virtual string Text {
get { return _text; }
set {
_text = value;
SqlHelper.ExecuteNonQuery("UPDATE umbracoNode SET text = @text WHERE id = @id",
SqlHelper.CreateParameter("@text", value),
SqlHelper.CreateParameter("@id", this.Id));
}
}
/// <summary>
/// The menu items used in the tree view
/// </summary>
public virtual BusinessLogic.console.MenuItemI[] MenuItems {
get { return new BusinessLogic.console.MenuItemI[0]; }
}
/// <summary>
/// Not implemented, always returns "about:blank"
/// </summary>
public virtual string DefaultEditorURL {
get { return "about:blank"; }
}
/// <summary>
/// The icon in the tree
/// </summary>
public virtual string Image {
get { return m_image; }
set { m_image = value; }
}
/// <summary>
/// The "open/active" icon in the tree
/// </summary>
public virtual string OpenImage {
get { return ""; }
}
#endregion
/// <summary>
/// An comma separated string consisting of integer node id's
/// that indicates the path from the topmost node to the given node
/// </summary>
/// <value>The path.</value>
public string Path {
get { return _path; }
set {
_path = value;
SqlHelper.ExecuteNonQuery("update umbracoNode set path = '" + _path + "' where id = " + this.Id.ToString());
}
}
/// <summary>
/// Updates the temp path for the content tree.
/// </summary>
/// <param name="Path">The path.</param>
protected void UpdateTempPathForTree(string Path) {
this._path = Path;
}
/// <summary>
/// Moves the CMSNode from the current position in the hierarchy to the target
/// </summary>
/// <param name="NewParentId">Target CMSNode id</param>
public void Move(int NewParentId) {
MoveEventArgs e = new MoveEventArgs();
FireBeforeMove(e);
if (!e.Cancel) {
int maxSortOrder = SqlHelper.ExecuteScalar<int>(
"select coalesce(max(sortOrder),0) from umbracoNode where parentid = @parentId",
SqlHelper.CreateParameter("@parentId", NewParentId));
CMSNode n = new CMSNode(NewParentId);
this.Parent = n;
this.Level = n.Level + 1;
this.Path = n.Path + "," + this.Id.ToString();
this.sortOrder = maxSortOrder + 1;
if (n.nodeObjectType == web.Document._objectType) {
Document d =
new umbraco.cms.businesslogic.web.Document(n.Id);
d.XmlGenerate(new XmlDocument());
d.Index(true);
} else if (n.nodeObjectType == media.Media._objectType)
new umbraco.cms.businesslogic.media.Media(n.Id).XmlGenerate(new XmlDocument());
foreach (CMSNode c in this.Children)
c.Move(this.Id);
FireAfterMove(e);
}
}
/// <summary>
/// Returns an integer value that indicates in which level of the
/// tree structure the given node is
/// </summary>
/// <value>The level.</value>
public int Level {
get { return _level; }
set {
_level = value;
SqlHelper.ExecuteNonQuery("update umbracoNode set level = " + _level.ToString() + " where id = " + this.Id.ToString());
}
}
/// <summary>
/// All CMSNodes has an objecttype ie. Webpage, StyleSheet etc., used to distinguish between the different
/// object types for for fast loading children to the tree.
/// </summary>
/// <value>The type of the node object.</value>
public Guid nodeObjectType {
get { return _nodeObjectType; }
}
/// <summary>
/// Besides the hierarchy it's possible to relate one CMSNode to another, use this for alternative
/// non-strict hierarchy
/// </summary>
/// <value>The relations.</value>
public relation.Relation[] Relations {
get { return relation.Relation.GetRelations(this.Id); }
}
/// <summary>
/// Does the current CMSNode have any child nodes.
/// </summary>
/// <value>
/// <c>true</c> if this instance has children; otherwise, <c>false</c>.
/// </value>
public virtual bool HasChildren {
get {
if (!_hasChildrenInitialized) {
int tmpChildrenCount = SqlHelper.ExecuteScalar<int>("select count(id) from umbracoNode where ParentId = " + _id);
HasChildren = (tmpChildrenCount > 0);
}
return _hasChildren;
}
set {
_hasChildrenInitialized = true;
_hasChildren = value;
}
}
/// <summary>
/// The basic recursive tree pattern
/// </summary>
/// <value>The children.</value>
public virtual BusinessLogic.console.IconI[] Children {
get {
System.Collections.ArrayList tmp = new System.Collections.ArrayList();
IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoNode where ParentID = " + this.Id + " And nodeObjectType = @type order by sortOrder",
SqlHelper.CreateParameter("@type", this.nodeObjectType));
while (dr.Read())
tmp.Add(dr.GetInt("Id"));
dr.Close();
CMSNode[] retval = new CMSNode[tmp.Count];
for (int i = 0; i < tmp.Count; i++)
retval[i] = new CMSNode((int)tmp[i]);
return retval;
}
}
/// <summary>
/// Retrieve all CMSNodes in the umbraco installation
/// Use with care.
/// </summary>
/// <value>The children of all object types.</value>
public BusinessLogic.console.IconI[] ChildrenOfAllObjectTypes {
get {
System.Collections.ArrayList tmp = new System.Collections.ArrayList();
IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoNode where ParentID = " + this.Id + " order by sortOrder");
while (dr.Read())
tmp.Add(dr.GetInt("Id"));
dr.Close();
CMSNode[] retval = new CMSNode[tmp.Count];
for (int i = 0; i < tmp.Count; i++)
retval[i] = new CMSNode((int)tmp[i]);
return retval;
}
}
/// <summary>
/// Retrieves the top level nodes in the hierarchy
/// </summary>
/// <param name="ObjectType">The Guid identifier of the type of objects</param>
/// <returns>
/// A list of all top level nodes given the objecttype
/// </returns>
protected static Guid[] TopMostNodeIds(Guid ObjectType) {
IRecordsReader dr = SqlHelper.ExecuteReader("Select uniqueID from umbracoNode where nodeObjectType = @type And parentId = -1 order by sortOrder",
SqlHelper.CreateParameter("@type", ObjectType));
System.Collections.ArrayList tmp = new System.Collections.ArrayList();
while (dr.Read()) tmp.Add(dr.GetGuid("uniqueID"));
dr.Close();
Guid[] retval = new Guid[tmp.Count];
for (int i = 0; i < tmp.Count; i++) retval[i] = (Guid)tmp[i];
return retval;
}
/// <summary>
/// Given the protected modifier the CMSNode.MakeNew method can only be accessed by
/// derived classes &gt; who by definition knows of its own objectType.
/// </summary>
/// <param name="parentId">The parent CMSNode id</param>
/// <param name="objectType">The objecttype identifier</param>
/// <param name="userId">Creator</param>
/// <param name="level">The level in the tree hieararchy</param>
/// <param name="text">The name of the CMSNode</param>
/// <param name="uniqueID">The unique identifier</param>
/// <returns></returns>
protected static CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) {
CMSNode parent;
string path = "";
int sortOrder = 0;
if (level > 0) {
parent = new CMSNode(parentId);
sortOrder = parent.Children.Length + 1;
path = parent.Path;
} else
path = "-1";
// Ruben 8/1/2007: I replace this with a parameterized version.
// But does anyone know what the 'level++' is supposed to be doing there?
// Nothing obviously, since it's a postfix.
SqlHelper.ExecuteNonQuery("INSERT INTO umbracoNode(trashed, parentID, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text) VALUES(@trashed, @parentID, @nodeObjectType, @nodeUser, @level, @path, @sortOrder, @uniqueID, @text)",
SqlHelper.CreateParameter("@trashed", 0),
SqlHelper.CreateParameter("@parentID", parentId),
SqlHelper.CreateParameter("@nodeObjectType", objectType),
SqlHelper.CreateParameter("@nodeUser", userId),
SqlHelper.CreateParameter("@level", level++),
SqlHelper.CreateParameter("@path", path),
SqlHelper.CreateParameter("@sortOrder", sortOrder),
SqlHelper.CreateParameter("@uniqueID", uniqueID),
SqlHelper.CreateParameter("@text", text));
CMSNode retVal = new CMSNode(uniqueID);
retVal.Path = path + "," + retVal.Id.ToString();
//event
NewEventArgs e = new NewEventArgs();
retVal.FireAfterNew(e);
return retVal;
}
/// <summary>
/// Retrieve a list of the unique id's of all CMSNodes given the objecttype
/// </summary>
/// <param name="objectType">The objecttype identifier</param>
/// <returns>
/// A list of all unique identifiers which each are associated to a CMSNode
/// </returns>
public static Guid[] getAllUniquesFromObjectType(Guid objectType) {
IRecordsReader dr = SqlHelper.ExecuteReader("Select uniqueID from umbracoNode where nodeObjectType = @type",
SqlHelper.CreateParameter("@type", objectType));
System.Collections.ArrayList tmp = new System.Collections.ArrayList();
while (dr.Read()) tmp.Add(dr.GetGuid("uniqueID"));
dr.Close();
Guid[] retval = new Guid[tmp.Count];
for (int i = 0; i < tmp.Count; i++) retval[i] = (Guid)tmp[i];
return retval;
}
/// <summary>
/// Retrieve a list of the node id's of all CMSNodes given the objecttype
/// </summary>
/// <param name="objectType">The objecttype identifier</param>
/// <returns>
/// A list of all node ids which each are associated to a CMSNode
/// </returns>
public static int[] getAllUniqueNodeIdsFromObjectType(Guid objectType) {
IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @type",
SqlHelper.CreateParameter("@type", objectType));
System.Collections.ArrayList tmp = new System.Collections.ArrayList();
while (dr.Read()) tmp.Add(dr.GetInt("id"));
dr.Close();
return (int[])tmp.ToArray(typeof(int));
}
/// <summary>
/// Retrieve a list of the id's of all CMSNodes given the objecttype and the first letter of the name.
/// </summary>
/// <param name="objectType">The objecttype identifier</param>
/// <param name="letter">Firstletter</param>
/// <returns>
/// A list of all CMSNodes which has the objecttype and a name that starts with the given letter
/// </returns>
protected static int[] getUniquesFromObjectTypeAndFirstLetter(Guid objectType, char letter) {
using (IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @objectType AND text like @letter", SqlHelper.CreateParameter("@objectType", objectType), SqlHelper.CreateParameter("@letter", letter.ToString() + "%"))) {
List<int> tmp = new List<int>();
while (dr.Read()) tmp.Add(dr.GetInt("id"));
return tmp.ToArray();
}
}
/// <summary>
/// Deletes this instance.
/// </summary>
public void delete() {
DeleteEventArgs e = new DeleteEventArgs();
FireBeforeDelete(e);
if (!e.Cancel) {
index.Indexer.RemoveNode(this.Id);
// remove relations
foreach (relation.Relation rel in Relations)
{
rel.Delete();
}
SqlHelper.ExecuteNonQuery("DELETE FROM umbracoNode WHERE uniqueID= @uniqueId", SqlHelper.CreateParameter("@uniqueId", _uniqueID));
FireAfterDelete(e);
}
}
/// <summary>
/// Get a count on all CMSNodes given the objecttype
/// </summary>
/// <param name="objectType">The objecttype identifier</param>
/// <returns>
/// The number of CMSNodes of the given objecttype
/// </returns>
public static int CountByObjectType(Guid objectType) {
return SqlHelper.ExecuteScalar<int>("SELECT COUNT(*) from umbracoNode WHERE nodeObjectType = @type", SqlHelper.CreateParameter("@type", objectType));
}
/// <summary>
/// Number of children of the current CMSNode
/// </summary>
/// <param name="Id">The CMSNode Id</param>
/// <returns>
/// The number of children from the given CMSNode
/// </returns>
public static int CountSubs(int Id) {
return SqlHelper.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoNode WHERE ','+path+',' LIKE '%," + Id.ToString() + ",%'");
}
/// <summary>
/// An xml representation of the CMSNOde
/// </summary>
/// <param name="xd">Xmldocument context</param>
/// <param name="Deep">If true the xml will append the CMSNodes child xml</param>
/// <returns>The CMSNode Xmlrepresentation</returns>
public virtual XmlNode ToXml(XmlDocument xd, bool Deep) {
XmlNode x = xd.CreateNode(XmlNodeType.Element, "node", "");
XmlPopulate(xd, x, Deep);
return x;
}
private void XmlPopulate(XmlDocument xd, XmlNode x, bool Deep) {
// attributes
x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString()));
if (this.Level > 1)
x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", this.Parent.Id.ToString()));
else
x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", "-1"));
x.Attributes.Append(xmlHelper.addAttribute(xd, "level", this.Level.ToString()));
x.Attributes.Append(xmlHelper.addAttribute(xd, "writerID", this.User.Id.ToString()));
x.Attributes.Append(xmlHelper.addAttribute(xd, "sortOrder", this.sortOrder.ToString()));
x.Attributes.Append(xmlHelper.addAttribute(xd, "createDate", this.CreateDateTime.ToString("s")));
x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text));
x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path));
if (Deep) {
foreach (Content c in this.Children)
x.AppendChild(c.ToXml(xd, true));
}
}
/// <summary>
/// Calls the subscribers of a cancelable event handler,
/// stopping at the event handler which cancels the event (if any).
/// </summary>
/// <typeparam name="T">Type of the event arguments.</typeparam>
/// <param name="cancelableEvent">The event to fire.</param>
/// <param name="sender">Sender of the event.</param>
/// <param name="eventArgs">Event arguments.</param>
protected virtual void FireCancelableEvent<T>(EventHandler<T> cancelableEvent, object sender, T eventArgs) where T : CancelEventArgs
{
if (cancelableEvent != null)
{
foreach (Delegate invocation in cancelableEvent.GetInvocationList())
{
invocation.DynamicInvoke(sender, eventArgs);
if (eventArgs.Cancel)
break;
}
}
}
/// <summary>
/// Occurs before a node is saved.
/// </summary>
public static event EventHandler<SaveEventArgs> BeforeSave;
/// <summary>
/// Raises the <see cref="E:BeforeSave"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireBeforeSave(SaveEventArgs e) {
FireCancelableEvent(BeforeSave, this, e);
}
/// <summary>
/// Occurs after a node is saved.
/// </summary>
public static event EventHandler<SaveEventArgs> AfterSave;
/// <summary>
/// Raises the <see cref="E:AfterSave"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterSave(SaveEventArgs e) {
if (AfterSave!=null)
AfterSave(this, e);
}
/// <summary>
/// Occurs after a new node is created.
/// </summary>
public static event EventHandler<NewEventArgs> AfterNew;
/// <summary>
/// Raises the <see cref="E:AfterNew"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterNew(NewEventArgs e) {
if (AfterNew != null)
AfterNew(this, e);
}
/// <summary>
/// Occurs before a node is deleted.
/// </summary>
public static event EventHandler<DeleteEventArgs> BeforeDelete;
/// <summary>
/// Raises the <see cref="E:BeforeDelete"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireBeforeDelete(DeleteEventArgs e) {
FireCancelableEvent(BeforeDelete, this, e);
}
/// <summary>
/// Occurs after a node is deleted.
/// </summary>
public static event EventHandler<DeleteEventArgs> AfterDelete;
/// <summary>
/// Raises the <see cref="E:AfterDelete"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterDelete(DeleteEventArgs e) {
if (AfterDelete != null)
AfterDelete(this, e);
}
/// <summary>
/// Occurs before a node is moved.
/// </summary>
public static event EventHandler<MoveEventArgs> BeforeMove;
/// <summary>
/// Raises the <see cref="E:BeforeMove"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireBeforeMove(MoveEventArgs e) {
FireCancelableEvent(BeforeMove, this, e);
}
/// <summary>
/// Occurs after a node is moved.
/// </summary>
public static event EventHandler<MoveEventArgs> AfterMove;
/// <summary>
/// Raises the <see cref="E:AfterMove"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterMove(MoveEventArgs e) {
if (AfterMove != null)
AfterMove(this, e);
}
}
}