рдЯреНрд░реА рд╡реНрдпреВ рд╡рд┐рде рд╕реАрдЖрд░рдпреВрдбреА рдСрдкрд░реЗрд╢рдВрд╕, рдбреНрд░реИрдЧ рдПрдВрдб рдбреНрд░реЙрдк (рдбреАрдПрдирдбреА) рдФрд░ рдбреАрдЬрд╝реЛрд░реНрдб рд▓реЛрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдбреЛрдЬреЛ рдЯреНрд░реА, рдПрдВрдЯрд┐рдЯреА рдлреНрд░реЗрдорд╡рд░реНрдХ, рдПрд╕рдХреНрдпреВрдПрд▓ рд╕рд░реНрд╡рд░ рдФрд░ рдПрдПрд╕рдкреА.рдиреЗрдЯ рдПрдорд╡реАрд╕реА

рдЫрд╡рд┐

рдкрд░рд┐рдЪрдп

рджреЛрдЬрд╝реЛ рдЯреВрд▓рдХрд┐рдЯ рдПрдХ рдУрдкрди-рд╕реЛрд░реНрд╕ рдореЙрдбреНрдпреВрд▓рд░ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИ рдЬрд┐рд╕реЗ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ / рдЕрдЬрд╛рдХреНрд╕-рдЙрдиреНрдореБрдЦ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдФрд░ рд╡реЗрдмрд╕рд╛рдЗрдЯреЛрдВ рдХреЗ рддреЗрдЬреА рд╕реЗ рд╡рд┐рдХрд╛рд╕ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдХреБрдЫ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдбреЛрдЬреЛ рдЯреНрд░реА рдШрдЯрдХ рдкрджрд╛рдиреБрдХреНрд░рдорд┐рдд рдбреЗрдЯрд╛ рдХрд╛ рдПрдХ рдкреВрд░реНрдг, рдкрд░рд┐рдЪрд┐рдд, рд╕рд╣рдЬ, рд╡рд┐рд╕реНрддрд╛рд░ рдпреЛрдЧреНрдп рдкреНрд░рд╕реНрддреБрддрд┐ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдШрдЯрдХ рд╡рд┐рд▓рдВрдмрд┐рдд рд╢рд╛рдЦрд╛ рд▓реЛрдбрд┐рдВрдЧ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЗрд╕реЗ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдЕрддреНрдпрдзрд┐рдХ рдорд╛рдкрдиреАрдп рдмрдирд╛рддрд╛ рд╣реИред Dojo рдЯреНрд░реА рдЕрднрд┐рднрд╛рд╡рдХ-рдмрдЪреНрдЪреЗ рдХреЗ рд░рд┐рд╢реНрддреЛрдВ рдХреЗ рд╕рд╛рде рдбреЗрдЯрд╛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╢рд╛рдирджрд╛рд░ рд╡рд┐рдЬреЗрдЯ рд╣реИред

рдпрд╣ рдЖрд▓реЗрдЦ рдПрдХ рдкреЗрдбрд╝ рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдЬреЛ CRUD рд╕рдВрдЪрд╛рд▓рди, рдЦреАрдВрдЪреЗрдВ рдФрд░ рдбреНрд░реЙрдк (DnD) рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд▓реЛрдб рдХрд░рдиреЗ рдореЗрдВ рджреЗрд░реА рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рдкреЗрдбрд╝ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо Dojo Tree, Entity Framework, SQL Server рдФрд░ Asp .Net MVC рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред

рдЗрдХрд╛рдИ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдПрдорд╡реАрд╕реА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдирд╛

рдпрд╣ рдЙрджрд╛рд╣рд░рдг Entity Framework "рдореЙрдбрд▓ рдкрд╣рд▓реЗ" рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдк рдЕрдиреНрдп рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ "рдХреЛрдб рдкрд╣рд▓реЗ" рдпрд╛ "рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд╣рд▓реЗ"ред рдЬреВрд▓реА рд▓рд░реНрдорди рдХрд╛ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рд▓реЗрдЦ рд╣реИ "рдпрд╣рд╛рдВ рдПрдХ рдкрд╣рд▓реЗ рдореЙрдбрд▓ рдФрд░ рдПрдВрдЯрд┐рдЯреА рдлреНрд░реЗрдорд╡рд░реНрдХ 4.1 рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдПрдХ рдПрдорд╡реАрд╕реА 3 рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдирд╛"ред рдЖрдк рдЕрдкрдиреЗ рдореЙрдбрд▓, рд╡рд░реНрдЧ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд▓реЗрдЦ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдФрд░ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдпрд╣рд╛рдВ рд╕рдорд░реНрдкрд┐рдд рд╣реЛрдЧрд╛ред

ASP.NET MVC рдореЗрдВ рд╢реНрд░реЗрд╖реНрда рд╕реЗрд╡рд╛

рдЪреВрдВрдХрд┐ Dojo JsonRest Store рд╕рдВрд╕реНрдерд╛рдУрдВ рдкрд░ CRUD рд╕рдВрдЪрд╛рд▓рди рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП JSON рдбреЗрдЯрд╛ рднреЗрдЬрддрд╛ рд╣реИ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ ASP.NET MVC 3. рдХреЗ рд╕рд╛рде рдПрдХ RESTful рд╕реЗрд╡рд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЖрдк рдЬрд╕реНрдЯрд┐рди Schwartzenberger рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд┐рдд рдПрдХ рдЕрдЪреНрдЫрд╛ рд▓реЗрдЦ "ASP.NET MVC рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдПрдХ рдмреЗрд╣рддрд░реАрди рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ API рдмрд┐рд▓реНрдбрд┐рдВрдЧ" рдпрд╣рд╛рдВ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред ред рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдХреБрдЫ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдЕрдкрдиреА ActionFilterAttribute рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдПрдХрд▓ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрдИ рд╕рдВрдЪрд╛рд▓рди (рдХреНрд░рд┐рдпрд╛) рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдПрдВрдЧреЗред рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореЙрдбрд▓ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдПрдХ рд╡рд░реНрдЧ ( RestHttpVerbFilter.cs ) рдмрдирд╛рдПрдВ:
 using System.Web.Mvc; namespace DojoTree.Models { public class RestHttpVerbFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var httpMethod = filterContext.HttpContext.Request.HttpMethod; filterContext.ActionParameters["httpVerb"] = httpMethod; base.OnActionExecuting(filterContext); } } } 

тАЬрдпрд╣ рдХреЛрдб рдЕрдиреБрд░реЛрдз рдХреЗ HTTP рд╕рдВрдЪрд╛рд▓рди (HTTP рдХреНрд░рд┐рдпрд╛) рдХреЛ рд░реЛрдХ рджреЗрдЧрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ ActionParameters рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛ред рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдкреИрд░рд╛рдореАрдЯрд░ httpVerb рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ RestHttpVerbFilter HTTP рдЕрдиреБрд░реЛрдз рдСрдкрд░реЗрд╢рди рдХреЗ рдореВрд▓реНрдп рдХреЗ рд▓рдЧрд╛рд╡ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░реЗрдЧрд╛ред рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рд╕рдорд╛рди рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдПрдХреНрд╢рди рд╡рд┐рдзрд┐ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди HTTP рдСрдкрд░реЗрд╢рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдирд╛ред рдПрдХ рд╣реА рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рд▓реЗрдХрд┐рди HTTP рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдЧреБрдгреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдХрд╕реНрдЯрдо рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣рдореЗрдВ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдПрдХреНрд╢рди рд╡рд┐рдзрд┐ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧреА, рдЬреЛ рдСрдкрд░реЗрд╢рди рдХреЗ рдирд┐рд░реНрдзрд╛рд░рдг рдХреЗ рддрд░реНрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд┐рдП рдмрд┐рдирд╛, HTTP рдСрдкрд░реЗрд╢рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░реЗрдЧреАред "[рем]

рдЖрджрд░реНрд╢

рдПрдХ рдореЙрдбрд▓ рд╡рд░реНрдЧ рдЬреЛрдбрд╝реЗрдВ рдЬрд┐рд╕рдореЗрдВ рдЯреНрд░реА рдиреЛрдбреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛред рд╢реНрд░реЗрдгреА рдФрд░ рдореЙрдбрд▓ рдХреЛ рд╕реВрдЪреА рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:
 public partial class Node { public int Id { get; set; } public int ParentId { get; set; } public string NodeName { get; set; } } 

рдЫрд╡рд┐

рд╡рд┐рдЪрд╛рд░

рд░реВрдЯ рдЬрдирд░реЗрд╢рди рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ "_Layout.cshtml" рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдореЗрдиреВ рдХрд╛ рднрд╛рдЧ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдирд╛ рд╣реЛрдЧрд╛:
  <ul id="menu"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink(" ", "generateRoot", "Home")</li> </ul> 

рдШрд░ / рдЙрддреНрдкрдиреНрди рджреГрд╢реНрдп

рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрдирд░реЗрдЯ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП рдПрдХ рджреГрд╢реНрдп рдмрдирд╛рдПрдВ:
 @{ ViewBag.Title = "generateRoot"; } <h2>@ViewBag.Message</h2> 

рдШрд░ / рд╕реВрдЪрдХрд╛рдВрдХ рджреГрд╢реНрдп

рдЗрд╕ рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдХреЛрдб:
 @{ ViewBag.Title = "Dojo Tree"; } <h2>@ViewBag.Message</h2> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/resources/dojo.css"> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dijit/themes/claro/claro.css"> <!-- load dojo and provide config via data attribute --> <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js" data-dojo-config="async: true, isDebug: true, parseOnLoad: true"></script> <script src="/js/tree.js" type="text/javascript"></script> <div style=" width: 400px; margin: 10px;"> <div id="tree"></div> </div> <div id="add-new-child"></div> <div id="remove-child"></div> 

рдЖрдк рдпрд╣рд╛рдБ рдКрдкрд░ рдФрд░ рдиреАрдЪреЗ рдХреЛрдб рднрд╛рдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрд░рд╛ рд▓реЗрдЦ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ js/tree.js рд▓рд┐рдВрдХ рд╣реИ, рдЗрд╕рдХреА рд╕рд╛рдордЧреНрд░реА рдиреАрдЪреЗ рдкреНрд░рд╕реНрддреБрдд рдХреА рдЧрдИ рд╣реИред

Js / tree.js рдХрд╛ рд╡рд┐рд╡рд░рдг

tree.js рдореЗрдВ рдХрдИ рднрд╛рдЧ рд╣реЛрддреЗ рд╣реИрдВ:

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдпрд╣ рд╣рд┐рд╕реНрд╕рд╛ рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ Dojo рдореЙрдбреНрдпреВрд▓ рдХреЛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ:
 require(["dojo/store/JsonRest", "dojo/store/Observable", "dojo/_base/Deferred", "dijit/Tree", "dijit/tree/dndSource", "dojox/form/BusyButton", "dojo/query", "dojo/domReady!"], function (JsonRest, Observable, Deferred, Tree, dndSource, BusyButton, query) { 


рдпрд╣ рднрд╛рдЧ "target: "/tree/data/"" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ TreeController рд▓рд┐рдП treeStore рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рддрд╛ рд╣реИред



 treeStore = JsonRest({ target: "/tree/data/", mayHaveChildren: function (object) { // see if it has a children property return "children" in object; }, getChildren: function (object, onComplete, onError) { // retrieve the full copy of the object this.get(object.id).then(function (fullObject) { // copy to the original object so it has the children array as well. object.children = fullObject.children; // now that full object, we should have an array of children onComplete(fullObject.children); }, function (error) { // an error occurred, log it, and indicate no children console.error(error); onComplete([]); }); }, getRoot: function (onItem, onError) { // get the root object, we will do a get() and callback the result this.get("1").then(onItem, function (error) { alert("Error loading Root"); }); }, getLabel: function (object) { // just get the name return object.NodeName; }, pasteItem: function (child, oldParent, newParent, bCopy, insertIndex) { // This will prevent to add a child to its parent again. if (child.ParentId == newParent.id) { return false; } var store = this; store.get(oldParent.id).then(function (oldParent) { store.get(newParent.id).then(function (newParent) { store.get(child.id).then(function (child) { var oldChildren = oldParent.children; dojo.some(oldChildren, function (oldChild, i) { if (oldChild.id == child.id) { oldChildren.splice(i, 1); return true; // done } }); store.put(oldParent); //This will change the parent of the moved Node child.ParentId = newParent.id; store.put(child); newParent.children.splice(insertIndex || 0, 0, child); store.put(newParent); }, function (error) { alert("Error loading " + child.NodeName); }); }, function (error) { alert("Error loading " + newParent.NodeName); }); }, function (error) { alert("Error loading " + oldParent.NodeName); }); }, put: function (object, options) { this.onChildrenChange(object, object.children); this.onChange(object); return JsonRest.prototype.put.apply(this, arguments); } }); 


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдпрд╣ рднрд╛рдЧ рдбреЛрдЬреЛ рдЯреНрд░реА рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ treeStore , рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдЪрд▓рд╛рддрд╛ рд╣реИ:
 tree = new Tree({ model: treeStore, dndController: dndSource }, "tree"); // make sure you have a target HTML element with this id tree.startup(); 


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЕрдЧрд▓рд╛ рднрд╛рдЧ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП "рдХреНрд▓рд╛рд░реЛ" рдереАрдо рдЬреЛрдбрд╝рддрд╛ рд╣реИ:
 dojo.query("body").addClass("claro"); 


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдпрд╣ рднрд╛рдЧ BusyButton рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ: addNewChildButton рдФрд░ removeChildButton ред
рдЖрдк рдЗрд╕ рдордж рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддреГрдд рджрд╕реНрддрд╛рд╡реЗрдЬ рдпрд╣рд╛рдВ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ ред
 var addNewChildButton = new BusyButton({ id: "add-new-child", busyLabel: "Wait a moment...", label: "Add new child to selected item", timeout: 500 }, "add-new-child"); var removeChildButton = new BusyButton({ id: "remove-child", busyLabel: "Wait a moment...", label: "Remove selected item", timeout: 500 }, "remove-child"); 


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдпрд╣ рд╣рд┐рд╕реНрд╕рд╛ add-new-child рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдХреЗ рдПрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдПрдХ рдЯреНрд░реА рдЖрдЗрдЯрдо рдЪреБрдирд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдлрд┐рд░, рдЪрдпрдирд┐рдд рдЪрдпрдирд┐рдд рдСрдмрдЬреЗрдХреНрдЯ рддрддреНрд╡ рдХреЛ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдпрджрд┐ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ, рддреЛ рдирдП рддрддреНрд╡ рдХрд╛ рдирд╛рдо рджрд░реНрдЬ рдХрд░рдирд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рдПрдХ рдирдпрд╛ newItem рддрддреНрд╡ newItem рдФрд░ рдЪрдпрдирд┐рдд рдЪрдпрдирд┐рдд newItem рддрддреНрд╡ рдХреЗ рдПрдХ рдмрдЪреНрдЪреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЙрд╕реЗ treeStore.put(newItem); рд╕рд░реНрд╡рд░ рдкрд░ рднреЗрдЬрд╛ рдЧрдпрд╛ рд╣реИ treeStore.put(newItem); ред 500 рдПрдордПрд╕ рдХреЗ рдмрд╛рдж, рдЪрдпрдирд┐рдд selectedObject рдСрдмрдЬреЗрдХреНрдЯ рдХреЛ рдЬреЛрдбрд╝реЗ рдЧрдП рдмрдЪреНрдЪреЗ рдХреА рдЖрдИрдбреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрдирдГ рд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред 500 рдПрдордПрд╕ рдХреЗ рдмрд╛рдж рд░рд┐рдмреВрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо "Deferred.when/dojo.when" рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред
 query("#add-new-child").on("click", function () { var selectedObject = tree.get("selectedItems")[0]; if (!selectedObject) { return alert("No object selected"); } //Sync selectedObject with server treeStore.get(selectedObject.id).then(function (selectedObject) { var name = prompt("Enter a name for new node"); if (name != null && name != "") { var newItem = { NodeName: name, ParentId: selectedObject.id, children: "" }; selectedObject.children.push(newItem); treeStore.put(newItem); //Loading recently added node 500ms after puting it var nodeId = new Deferred(); Deferred.when(nodeId, reloadNode); setTimeout(function () { nodeId.resolve(selectedObject.id); }, 500); } else { return alert("Name can not be empty."); } }, function (error) { alert("Error loading " + selectedObject.NodeName); }); }); 


рдпрд╣ рднрд╛рдЧ remove-child рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдПрдХ рддрддреНрд╡ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рдФрд░ рдЪрдпрдирд┐рдд рддрддреНрд╡ рдкреЗрдбрд╝ рдХреА рдЬрдбрд╝ рдирд╣реАрдВ рд╣реИред рдлрд┐рд░, рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдкреБрд╖реНрдЯрд┐рдХрд░рдг рд╕рдВрджреЗрд╢: "рдХреНрдпрд╛ рдЖрдк рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реИрдВ рдХрд┐ рдЖрдк рдЗрд╕ рдиреЛрдб рдФрд░ рдЗрд╕рдХреЗ рд╕рднреА рд╡рдВрд╢рдЬреЛрдВ рдХреЛ рд╕реНрдерд╛рдпреА рд░реВрдк рд╕реЗ рд╣рдЯрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?" рдпрджрд┐ рдЙрддреНрддрд░ рд╣рд╛рдБ рд╣реИ, рддреЛ рдЪрдпрдирд┐рддрдСрдмрдЬреЗрдХреНрдЯ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдпрджрд┐ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ, рддреЛ рд╡рд┐рдзрд┐ рд╕рднреА рд╡рдВрд╢рдЬ рдХреЛ рд╣рдЯрд╛ рджреЗрдЧреА рдФрд░ рдЪрдпрдирд┐рдд рдиреЛрдб рдЦреБрдж рд╣реА рд╣рдЯрд╛ рджреЗрдЧрд╛ removeAllChildren(selectedObject); ред 500 рдПрдордПрд╕ рдХреЗ рдмрд╛рдж, рдЪрдпрдирд┐рдд рддрддреНрд╡ рдХреЗ рдорд╛рддрд╛-рдкрд┐рддрд╛ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ selectedObject.ParentId ред PententId рдкреБрдирдГ рд▓реЛрдб рдХрд┐рдпрд╛ selectedObject.ParentId ред
 query("#remove-child").on("click", function () { var selectedObject = tree.get("selectedItems")[0]; if (!selectedObject) { return alert("No object selected"); } if (selectedObject.id == 1) { return alert("Can not remove Root Node"); } var answer = confirm("Are you sure you want to permanently delete this node and all its children?") if (answer) { treeStore.get(selectedObject.id).then(function (selectedObject) { removeAllChildren(selectedObject); //Reloading the parent of recently removed node 500ms after removing it var ParentId = new Deferred(); Deferred.when(ParentId, reloadNode); setTimeout(function () { ParentId.resolve(selectedObject.ParentId); }, 500); }, function (error) { alert("Error loading " + selectedObject.NodeName); }); } }); 


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдпрд╣ рднрд╛рдЧ рдЯреНрд░реА рдиреЛрдб рдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдбрдмрд▓-рдХреНрд▓рд┐рдХ dblclick рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЪрдпрдирд┐рдд рдЖрдЗрдЯрдо рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ, рддреЛ рдиреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдирд╛рдо рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд┐рд░ рдирдпрд╛ рдирд╛рдо treeStore.put(object) рд╕рд░реНрд╡рд░ рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  tree.on("dblclick", function (object) { treeStore.get(object.id).then(function (object) { var name = prompt("Enter a new name for the object"); if (name != null && name != "") { object.NodeName = name; treeStore.put(object).then(function () { }, function (error) { // On Error revert Value reloadNode(object.ParentId); alert("Error renaming " + object.NodeName); }); } else { return alert("Name can not be empty."); } }, function (error) { alert("Error loading " + object.NodeName); }); }, true); }); 


рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдЖрдИрдбреА рдФрд░ рдЙрд╕реА рд╕реНрддрд░ рдХреЗ рд╕рднреА рд╡рдВрд╢рдЬреЛрдВ рдХреЗ рдореВрд▓реНрдп рд╕реЗ рдиреЛрдб рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИред
 function reloadNode(id) { treeStore.get(id).then(function (Object) { treeStore.put(Object); }) }; 


рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдиреЛрдб рдХреЗ рд╕рднреА рд╡рдВрд╢реЛрдВ рдХреЛ рдкреБрди: рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИред
 function removeAllChildren(node) { treeStore.get(node.id).then(function (node) { var nodeChildren = node.children; for (n in nodeChildren) { removeAllChildren(nodeChildren[n]); } treeStore.remove(node.id); }, function (error) { alert(error); }); }; 


рдирд┐рдпрдВрддреНрд░рдХ

рдЕрдм рдЖрдкрдХреЛ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

TreeController

рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ "TreeController.cs": рдореЗрдВ рдХреЙрдкреА рдХрд░реЗрдВ "TreeController.cs":
 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Data.Entity; using DojoTree.Models; using System.Data; using System.Net; namespace DojoTree.Controllers { public class TreeController : Controller { private TreeModelContainer db = new TreeModelContainer(); // GET /Tree/Data/3 // POST /Tree/Data // PUT /Tree/Data/3 // DELETE /Tree/Data/3 [RestHttpVerbFilter] public JsonResult Data(Node node, string httpVerb, int id = 0) { switch (httpVerb) { case "POST": if (ModelState.IsValid) { db.Entry(node).State = EntityState.Added; db.SaveChanges(); return Json(node, JsonRequestBehavior.AllowGet); } else { Response.TrySkipIisCustomErrors = true; Response.StatusCode = (int)HttpStatusCode.NotAcceptable; return Json(new { Message = "Data is not Valid." }, JsonRequestBehavior.AllowGet); } case "PUT": if (ModelState.IsValid) { db.Entry(node).State = EntityState.Modified; db.SaveChanges(); return Json(node, JsonRequestBehavior.AllowGet); } else { Response.TrySkipIisCustomErrors = true; Response.StatusCode = (int)HttpStatusCode.NotAcceptable; return Json(new { Message = "Node " + id + " Data is not Valid." }, JsonRequestBehavior.AllowGet); } case "GET": try { var node_ = from entity in db.Nodes.Where(x => x.Id.Equals(id)) select new { id = entity.Id, NodeName = entity.NodeName, ParentId = entity.ParentId, children = from entity1 in db.Nodes.Where (y => y.ParentId.Equals(entity.Id)) select new { id = entity1.Id, NodeName = entity1.NodeName, ParentId = entity1.ParentId, children = "" // it calls checking children // whenever needed } }; var r = node_.First(); return Json(r, JsonRequestBehavior.AllowGet); } catch { Response.TrySkipIisCustomErrors = true; Response.StatusCode = (int)HttpStatusCode.NotAcceptable; return Json(new { Message = "Node " + id + " does not exist." }, JsonRequestBehavior.AllowGet); } case "DELETE": try { node = db.Nodes.Single(x => x.Id == id); db.Nodes.Remove(node); db.SaveChanges(); return Json(node, JsonRequestBehavior.AllowGet); } catch { Response.TrySkipIisCustomErrors = true; Response.StatusCode = (int)HttpStatusCode.NotAcceptable; return Json(new { Message = "Could not delete Node " + id }, JsonRequestBehavior.AllowGet); } } return Json(new { Error = true, Message = "Unknown HTTP verb" }, JsonRequestBehavior.AllowGet); } } } 


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдирд┐рдпрдВрддреНрд░рдХ рдПрдХрд▓ URL "/Tree/Data/" "GET / POST / PUT / DELETE" рдСрдкрд░реЗрд╢рди рдХрд░рддрд╛ рд╣реИ, рдпрд╣ RestHttpVerbFilter рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рдзрдиреНрдпрд╡рд╛рдж рд╣реИред


HomeController

рдореИрдВрдиреЗ рдХреЗрд╡рд▓ рдЯреНрд░реА рд░реВрдЯ рдЬреЗрдирд░реЗрд╢рди рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП HomeController рдмрджрд▓ рджрд┐рдпрд╛ред рдЕрдкрдиреЗ HomeController рдХреЛ рдирд┐рдореНрди рдореЗрдВ рд▓рд╛рдПрдБ:
 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using DojoTree.Models; namespace DojoTree.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Tree supporting CRUD operations Using Dojo Tree, Entity Framework, Asp .Net MVC"; return View(); } public ActionResult generateRoot() { try { TreeModelContainer db = new TreeModelContainer(); Node node = new Node(); node= db.Nodes.Find(1); if (node == null) { //If you deleted Root manually, this couldn't make Root again //because Root Id must be "1", so you must drop the //Tree table and rebuild it //or change the Root Id in "tree.js" Node rootNode = new Node(); rootNode.NodeName = "Root"; rootNode.ParentId = 0; db.Nodes.Add(rootNode); db.SaveChanges(); ViewBag.Message = "Some Nodes have been generated"; } else { ViewBag.Message = "Root Exists."; } } catch { ViewBag.Message = "An Error occurred"; } return View(); } } } 


рджреГрд╢реНрдп рдкреНрд░рджрд░реНрд╢рди

рдЕрдм рдкрд░рд┐рдгрд╛рдо рджреЗрдЦрдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рдПрдХ рд╕рдорд╛рдзрд╛рди рдмрдирд╛рдПрдБ рдФрд░ рд░реВрдЯ рдкреАрдврд╝реА рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ, рдлрд┐рд░ рдЬреЛрдбрд╝реЗрдВ | рдирд╛рдо рдмрджрд▓реЗрдВ | рдЦреАрдВрдЪреЗрдВ рдФрд░ рдкреЗрд╕реНрдЯ | рдХрд┐рд╕реА рднреА рдкреЗрдбрд╝ рдХреЗ рдиреЛрдбреНрд╕ рдХреЛ рд╣рдЯрд╛ рджреЗрдВред
рдЫрд╡рд┐
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдлрд╛рдпрд░рдмрдЧ рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдбреЗрдЯрд╛ Json REST рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреЗрдЬрд╛ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╕рдВрджрд░реНрдн

рдпрд╣ рд╕рд╛рдордЧреНрд░реА "рдЯреНрд░реА рд╡реНрдпреВ рд╡рд┐рде" рд╕реАрдЖрд░рдпреВрдбреА рдСрдкрд░реЗрд╢рдВрд╕ "," рдбреНрд░реИрдЧ рдПрдВрдб рдбреНрд░реЙрдк (рдбреАрдПрдирдбреА) "рдФрд░" рдЖрд▓рд╕реА рд▓реЛрдбрд┐рдВрдЧ "рдХрд╛ рдЕрдиреБрд╡рд╛рдж рд╣реИ рдЬреЛ рдХрд┐ рдбреЛрдЬреЛ рдЯреНрд░реА, рдПрдВрдЯрд┐рдЯреА рдлреНрд░реЗрдорд╡рд░реНрдХ, рдПрд╕рдХреНрдпреВрдПрд▓ рд╕рд░реНрд╡рд░, рдПрдПрд╕рдкреА.рдиреЗрдЯ рдПрдорд╡реАрд╕реА" рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣рд╛рдВ рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред рд╡рд╣рд╛рдВ рдЖрдк рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

Source: https://habr.com/ru/post/In175571/


All Articles