[CLOSED] Desktop - drag menu item from StartMenu and drop as shortcut

  1. #1

    [CLOSED] Desktop - drag menu item from StartMenu and drop as shortcut

    Hello support team,
    is it possible to dynamically create desktop shortcuts for the selected StartMenu items of the Desktop? What I want to achieve is offer a user-friendly way to create a desktop icon for chosen StartMenu application. Is it possible to implement, for example, drag & drop for StartMenu items? I spent quite some time with looking for a solution and although I had no problem with drag & drop implementation for tree menu or droppable panels, here I'm lost.

    According to my simple example, I want to drag the menu item of the European Union and drop a new shortcut next to the Notepad shortcut. Is it feasible? Please, can you give me some clue?

    Ext.NET version 4.3

    Thank you,
    Dan

    @{
        Layout = null;
    
        List<MenuItem> startMenu = new List<Ext.Net.MenuItem>();
        startMenu.Add(new Ext.Net.MenuItem() { Icon = Icon.FlagEuropeanunion, Text = "European Union" });
        startMenu.Add(new Ext.Net.MenuItem() { Icon = Icon.FlagUs, Text = "United States" });
    }
    
    @Html.X().ResourceManager()
    
    @(Html.X().Desktop()
        .ID("_nelisDesktop")
        .Listeners(l => { l.Ready.Handler = " desktopReady()"; })
        .DesktopConfig(
            Html.X().DesktopConfig()
            .SortShortcuts(true)
                .WallpaperStretch(true)
                .ShortcutDragSelector(true)
        )
        .StartMenu(
            Html.X().DesktopStartMenu()
                .ID("_nelisDesktop_StartMenu")
                .Title("Allegro Desktop")
                .Icon(Icon.Application)
                .MenuItems(startMenu)
                .ToolConfig(
                    Html.X().Toolbar()
                        .Width(100)
                        .Items(
                            Html.X().Button()
                            .Icon(Icon.Calculator)
                            .Text("Calculator")
                        )
                )
        )
        .TaskBar(
            Html.X().DesktopTaskBar()
                .TrayWidth(40)
                .QuickStartWidth(75)
                .QuickStart(
                    Html.X().Toolbar()
                        .Items(
                            Html.X().Button()
                                .Icon(Icon.ApplicationTileVertical)
                                .ToolTip("Tile windows")
                                .OverflowText("Tile windows"),
                            Html.X().Button()
                                .Icon(Icon.ApplicationCascade)
                                .ToolTip("Cascade windows")
                                .OverflowText("Cascade windows"),
                            Html.X().Button()
                                .Icon(Icon.ApplicationViewIcons)
                                .ToolTip("Default icons positions")
                        )
                )
        )
        .Modules(
            Html.X().DesktopModule().ModuleID("Notepad").Shortcut(new DesktopShortcut { Name = "Notepad", IconCls = "x-notepad-shortcut" })
        )
    )
    
    <script type="text/javascript">
    
        var $desktop;
    
        function desktopReady() {
            $desktop = Nelis._nelisDesktop;
        }
    
    </script>
    Last edited by fabricio.murta; Sep 13, 2017 at 8:23 PM.
  2. #2
    Hello @Newlink!

    Well, the desktop does not natively support drag-dropping menu entries from the start menu to the desktop. But this does not mean it is impossible to attain that. But that would require a significant level of customization of the component. If you have little clue on where to start, I suggest you read thru this Sencha guide on Drag Drop using ExtJS.

    Then you can see some online examples with different levels of customization in drag drop. A good starting point would be the DOM DragDrop example (which is also shown in illustrations from the Sencha guide): MVC Examples Explorer - Drag Drop - Basic - DOM.

    There are then several other examples next to the one linked above, you can see how they are implemented to get insight on how to proceed adding drag-drop to the part of the desktop component where you need.

    A little more specificly, you'll have to bind a custom drag handler to the menu entry, carrying its menu entry text, maybe also encapsulating an unique ID to the menu entry, and then making a custom drop handler where, from the dropped item information, it will instantiate a dynamic module corresponding to that menu entry.

    Maybe the greatest challenge here would be mapping the menu entry to an actual desktop module/shortcut, once you have determined the drag and drop zones from the desktop.

    Unfortunately, as the feature is not native to the desktop, you'll have to go thru the customization process, but I really believe in the end you would find it was not as hard as it seemed to be. :)

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Hi FabrÃ*cio,
    thank you for your prompt reply. Before I opened this thread, I went through available examples and spent many hours trying different scenarios. Here is one based on the example you mentioned:

    @using Ext.Net;
    @using Ext.Net.MVC;
    
    @{
        ViewBag.Title = "Desktop Drag & Drop Example";
        Layout = null;
        var X = Html.X();
    
        List<MenuItem> startMenu = new List<Ext.Net.MenuItem>();
        startMenu.Add(new Ext.Net.MenuItem() { ID = "EU", Icon = Icon.FlagEuropeanunion, Text = "European Union" });
        startMenu.Add(new Ext.Net.MenuItem() { ID = "US", Icon = Icon.FlagUs, Text = "United States" });
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <title>Ext.NET MVC Test Case</title>
    
        <style>
            .dropOK {
                background-color: #99ff99 !important;
            }
            .dropNotOK {
                border: 1px solid #FF0000 !important;
            }
        </style>
    
        <script type="text/javascript">
            Ext.onReady(function () {
                console.log("onReady");
                console.log("EU", Ext.getCmp("EU"));
                console.log("dataview-1030", Ext.getCmp("dataview-1030"));
            });
    
            function desktopReady() {
                console.log("desktopReady");
                console.log("EU", Ext.getCmp("EU"));
                console.log("dataview-1030", Ext.getCmp("dataview-1030"));
            }
    
            Ext.ns("App").ddOverrides = {
                // Called the instant the element is dragged.
                startDrag: function () {
                    console.log("startDrag");
                    // Cache the drag "phantom" element
                    if (!this.dEl) {
                        this.dEl = Ext.get(this.getDragEl());
                    }
    
                    // Cache the original element
                    if (!this.el) {
                        this.el = Ext.get(this.getEl());
                    }
    
                    // Make the original icon less visible to indicate it is really about to be moved
                    this.el.applyStyles({ opacity: 0.4 });
    
                    this.dEl.applyStyles({
                        border: "",
                        // Trim the sides to 8 pixels to have it match the icons
                        width: (this.el.getWidth() - 8) + "px",
                        height: (this.el.getHeight() - 8) + "px",
                        "z-index": 2000
                    });
    
                    // Create an exact copy of the element on the cursor
                    this.dEl.update(this.el.dom.innerHTML);
    
                    // adding this class is the trick to have drop areas to work
                    // If you just avoid this and then use this.el.dom.outerHTML above, the mouse will
                    // be always above the div and will never trigger an dropEnter event.
                    this.dEl.addCls(this.el.dom.className);
    
                    this.lastTarget = null;
                },
    
                // Called when the drag operation completes
                endDrag: function () {
                    console.log("endDrag");
                    // Create the animation configuration object
                    var animCfgObj = {
                        easing: 'ease',
                        duration: 500,
                        opacity: 1,
                        scope: this,
                    };
    
                    // Invoke the animation according to the drop success/failure
                    if (this.lastTarget == null) {
                        // After dragging, remove transparency effect of moved element.
                        this.el.animate(animCfgObj);
                    } else {
                        // Remove the drop invitation
                        this.el.removeCls('dropOK');
    
                        // Get exact position where the drag-dropped item were released
                        var destXY = this.dEl.getXY();
    
                        animCfgObj.callback = function () {
                            // Remove the position attribute
                            this.el.dom.style.position = '';
    
                            // Finally, add the item to the target div
                            Ext.get(this.lastTarget).appendChild(this.el);
                        };
    
                        // animate icon to where the mouse dropped it
                        this.el.setXY([destXY[0], destXY[1]], animCfgObj);
                    }
                },
    
                // Only called when the drag element is dragged over the a drop target with the same ddgroup
                onDragEnter: function (evtObj, targetElId) {
                    console.log("onDragEnter");
                    // Colorize the drag target if the drag node's parent is not the same as the drop target
                    // and is valid for the car type
                    if (targetElId != this.el.dom.parentNode.id) {
                        this.el.addCls('dropOK');
                        this.dEl.addCls('dropOK');
                        this.lastTarget = Ext.get(targetElId);
                    } else {
                        // Remove the invitation
                        this.onDragOut();
                        this.lastTarget = null;
                    }
                },
    
                // Only called when element is dragged out of a dropzone with the same ddgroup
                onDragOut: function (evtObj, targetElId) {
                    console.log("onDragOut");
                    this.el.removeCls('dropOK');
                    this.dEl.removeCls('dropOK');
                    this.lastTarget = null;
                },
    
                onDrop: function (evtObj, targetElId) {
                    console.log("onDrop");
                }
            };
        </script>
    </head>
    
    <body>
        @Html.X().ResourceManager()
    
        @(Html.X().Desktop()
            .ID("_nelisDesktop").Listeners(l => l.Ready.Fn = "desktopReady")
            .DesktopConfig(
                Html.X().DesktopConfig()
                .SortShortcuts(true)
                    .WallpaperStretch(true)
                    .ShortcutDragSelector(true)
            )
            .StartMenu(
                Html.X().DesktopStartMenu()
                    .ID("_nelisDesktop_StartMenu")
                    .Title("Allegro Desktop")
                    .Icon(Icon.Application)
                    .MenuItems(startMenu)
                    .ToolConfig(
                        Html.X().Toolbar()
                            .Width(100)
                            .Items(
                                Html.X().Button()
                                .Icon(Icon.Calculator)
                                .Text("Calculator")
                            )
                    )
            )
            .TaskBar(
                Html.X().DesktopTaskBar()
                    .TrayWidth(40)
                    .QuickStartWidth(75)
                    .QuickStart(
                        Html.X().Toolbar()
                            .Items(
                                Html.X().Button()
                                    .Icon(Icon.ApplicationTileVertical)
                                    .ToolTip("Tile windows")
                                    .OverflowText("Tile windows"),
                                Html.X().Button()
                                    .Icon(Icon.ApplicationCascade)
                                    .ToolTip("Cascade windows")
                                    .OverflowText("Cascade windows"),
                                Html.X().Button()
                                    .Icon(Icon.ApplicationViewIcons)
                                    .ToolTip("Default icons positions")
                            )
                    )
            )
            .Modules(
                Html.X().DesktopModule().ModuleID("Notepad").Shortcut(new DesktopShortcut { Name = "Notepad", IconCls = "x-notepad-shortcut" })
            )
        )
    
        @(X.DDProxy()
            .Target("EU")
            .Group("desktopDD")
            .IsTarget(false)
            .StartDrag(a => a.Fn = "App.ddOverrides.startDrag")
            .EndDrag(a => a.Fn = "App.ddOverrides.endDrag")
            .OnDragEnter(a => a.Fn = "App.ddOverrides.onDragEnter")
            .OnDragOut(a => a.Fn = "App.ddOverrides.onDragOut")
        )
    
        @(X.DDProxy()
            .Target("US")
            .Group("desktopDD")
            .IsTarget(false)
            .StartDrag(a => a.Fn = "App.ddOverrides.startDrag")
            .EndDrag(a => a.Fn = "App.ddOverrides.endDrag")
            .OnDragEnter(a => a.Fn = "App.ddOverrides.onDragEnter")
            .OnDragOut(a => a.Fn = "App.ddOverrides.onDragOut")
        )
    
        @(X.DropZone().Target("dataview-1030").Group("desktopDD").NotifyDrop(a => a.Fn = "App.ddOverrides.onDrop").OnDragDrop(a => a.Fn = "App.ddOverrides.onDrop"))
    </body>
    </html>
    Unfortunately, it does not work, events are triggered differently than I would expect and dragged item cannot be dropped. I also have problem to specify target for drop zone, as pointing to '_nelisDesktop' does not work because no component with such ID is rendered.

    But even your example does not work: http://mvc4.ext.net/#/DragDrop_Basic/Dom/

    I copied the code in my project and found out that the events did not work the same way as in my test case and a car cannot be dropped:

    @using Ext.Net;
    @using Ext.Net.MVC;
    
    @{
        ViewBag.Title = "Drag and Drop with DOM Elements - Ext.NET MVC Examples";
        Layout = null;
        var X = Html.X();}
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <title>Ext.NET MVC Test Case</title>
    
        <style>
            body {
                padding: 10px;
            }
            .availableLot {
                width: 103px;
                border: 1px solid #999999;
                padding: 10px;
                height: 310px;
                margin: 10px;
                -moz-border-radius: 17px;
                -webkit-border-radius: 17px;
                border-radius: 17px;
            }
            .rented, .repair {
                width: 195px;
            }
            .vehicleIcon {
                -moz-border-radius: 5px;
                -webkit-border-radius: 5px;
                border-radius: 5px;
                width: 85px;
                border: 1px solid #666666;
                padding: 3px;
                background-color: #FFFFFF;
                margin: 5px;
                cursor: move;
                text-align: center;
            }
            #cars div, #trucks div {
                margin: 5px;
                width: 85px;
            }
            #repair div, #rented div {
                float: left;
                margin: 2px;
            }
            .imgThumb {
                position: relative;
                top: 2px;
                height: 57px;
                width: 77px;
                border: 1px solid #777777;
            }
            .dropOK {
                background-color: #99ff99 !important;
            }
            .dropNotOK {
                border: 1px solid #FF0000 !important;
            }
        </style>
        
        <script type="text/javascript">
            Ext.ns("App").ddOverrides = {
                // Called the instant the element is dragged.
                startDrag: function () {
                    console.log("startDrag");
                    // Cache the drag "phantom" element
                    if (!this.dEl) {
                        this.dEl = Ext.get(this.getDragEl());
                    }
    
                    // Cache the original element
                    if (!this.el) {
                        this.el = Ext.get(this.getEl());
                    }
    
                    // Make the original icon less visible to indicate it is really about to be moved
                    this.el.applyStyles({ opacity: 0.4 });
    
                    this.dEl.applyStyles({
                        border: "",
                        // Trim the sides to 8 pixels to have it match the icons
                        width: (this.el.getWidth() - 8) + "px",
                        height: (this.el.getHeight() - 8) + "px",
                        "z-index": 2000
                    });
    
                    // Create an exact copy of the element on the cursor
                    this.dEl.update(this.el.dom.innerHTML);
    
                    // adding this class is the trick to have drop areas to work
                    // If you just avoid this and then use this.el.dom.outerHTML above, the mouse will
                    // be always above the div and will never trigger an dropEnter event.
                    this.dEl.addCls(this.el.dom.className);
    
                    this.lastTarget = null;
                },
    
                // Called when the drag operation completes
                endDrag: function () {
                    console.log("endDrag");
                    // Create the animation configuration object
                    var animCfgObj = {
                        easing: 'ease',
                        duration: 500,
                        opacity: 1,
                        scope: this,
                    };
    
                    // Invoke the animation according to the drop success/failure
                    if (this.lastTarget == null) {
                        // After dragging, remove transparency effect of moved element.
                        this.el.animate(animCfgObj);
                    } else {
                        // Remove the drop invitation
                        this.el.removeCls('dropOK');
    
                        // Get exact position where the drag-dropped item were released
                        var destXY = this.dEl.getXY();
    
                        animCfgObj.callback = function () {
                            // Remove the position attribute
                            this.el.dom.style.position = '';
    
                            // Finally, add the item to the target div
                            Ext.get(this.lastTarget).appendChild(this.el);
                        };
    
                        // animate icon to where the mouse dropped it
                        this.el.setXY([destXY[0], destXY[1]], animCfgObj);
                    }
                },
    
                // Only called when the drag element is dragged over the a drop target with the same ddgroup
                onDragEnter: function (evtObj, targetElId) {
                    console.log("onDragEnter");
                    var vehicleAllowed = true;
    
                    // Determine if currently selected car type is allowed in the drop area
                    if ((this.el.id.indexOf("truck") == 0 && targetElId == "cars") ||
                        (this.el.id.indexOf("car") == 0 && targetElId == "trucks")) {
                        vehicleAllowed = false;
                    };
    
                    // Colorize the drag target if the drag node's parent is not the same as the drop target
                    // and is valid for the car type
                    if (targetElId != this.el.dom.parentNode.id && vehicleAllowed) {
                        this.el.addCls('dropOK');
                        this.dEl.addCls('dropOK');
                        this.lastTarget = Ext.get(targetElId);
                    } else {
                        // Remove the invitation
                        this.onDragOut();
                        this.lastTarget = null;
                    }
                },
    
                // Only called when element is dragged out of a dropzone with the same ddgroup
                onDragOut: function (evtObj, targetElId) {
                    console.log("onDragOut");
                    this.el.removeCls('dropOK');
                    this.dEl.removeCls('dropOK');
                    this.lastTarget = null;
                }
            };
        </script>
    </head>
    
    <body>
        <table class="x-unselectable">
            <tr>
                <td>
                    <table>
                        <tr>
                            <td align='center'>
                                Available Cars
                            </td>
                            <td align='center'>
                                Available Trucks
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <div id="cars" class="availableLot">
                                    <div id="carCamaro" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/camaro.jpg")" class="imgThumb" qtip="Camaro" /></div>
                                    <div id="carMiata" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/miata.jpg")" class="imgThumb" qtip="Miata" /></div>
                                    <div id="carMustang" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/mustang.jpg")" class="imgThumb" qtip="Mustang" /></div>
                                    <div id="carCorvette" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/corvette.jpg")" class="imgThumb" qtip="Corvette" /></div>
                                </div>
                            </td>
                            <td>
                                <div id="trucks" class="availableLot trucksLot">
                                    <div id="truckF150" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/f150.jpg")" class="imgThumb" qtip="F150" /></div>
                                    <div id="truckTahoe" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/tahoe.jpg")" class="imgThumb" qtip="Tahoe" /></div>
                                    <div id="truckTacoma" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/tacoma.jpg")" class="imgThumb" qtip="Tacoma" /></div>
                                    <div id="truckS10" class="vehicleIcon"><img src="http://mvc4.ext.net/Areas/DragDrop_Basic/Content/images/s10.jpg")" class="imgThumb" qtip="S10" /></div>
                                </div>
                            </td>
                        </tr>
    
                    </table>
                </td>
                <td align='center' style="width: 200px;">
                    <table>
                        <tr>
                            <td align='center' style="width: 200px;">
                                Vehicles Rented
                            </td>
                            <td align='center' style="width: 200px;">
                                Vehicles In Repair
                            </td>
                        </tr>
                        <tr style="">
                            <td style="">
                                <div id="rented" class="availableLot rented"></div>
                            </td>
                            <td>
                                <div id="repair" class="availableLot repair"></div>
                            </td>
                        </tr>
    
                    </table>
                </td>
            </tr>
        </table>
    
        @Html.X().ResourceManager()
    
        @* Set as drag zones on every item inside both the cars and trucks divs *@
        @(X.DDProxy()
            .Target("${#cars div}")
            .Group("carsDDGroup")
            .IsTarget(false)
            .StartDrag(a => a.Fn = "App.ddOverrides.startDrag")
            .EndDrag(a => a.Fn = "App.ddOverrides.endDrag")
            .OnDragEnter(a => a.Fn = "App.ddOverrides.onDragEnter")
            .OnDragOut(a => a.Fn = "App.ddOverrides.onDragOut")
        )
    
        @(X.DDProxy()
            .Target("${#trucks div}")
            .Group("carsDDGroup")
            .IsTarget(false)
            .StartDrag(a => a.Fn = "App.ddOverrides.startDrag")
            .EndDrag(a => a.Fn = "App.ddOverrides.endDrag")
            .OnDragEnter(a => a.Fn = "App.ddOverrides.onDragEnter")
            .OnDragOut(a => a.Fn = "App.ddOverrides.onDragOut")
        )
    
        @* Set as drop zones both 'rented' and 'repair' divs *@
        @(X.DropZone().Target("rented").Group("carsDDGroup"))
        @(X.DropZone().Target("repair").Group("carsDDGroup"))
    
        @* Set drop zones on cars and trucks divs (they're specially treated to allow correct items back) *@
        @(X.DropZone().Target("cars").Group("carsDDGroup"))
        @(X.DropZone().Target("trucks").Group("carsDDGroup"))
    </body>
    </html>
    Can you please help me with the right solution? Thank you.

    Dan
  4. #4
    Hello @NewLink!

    You are right! We'll need to take a look on why that example is not working, maybe you are doing the right thing and it does not work because of that drag drop bug on the live example!

    The other dragdrop examples there works right, and should be able to help you out on more issues as they appear. Please also take a look at the WebForms drag drop examples, there are some more than MVC, and showing more aspects that may help.

    Well, as for the developed code sample you provided, I could make it further work if I dropped DDProxy in favor of DragSource. I believe this will do for you, check it out:

    @using Ext.Net;
    @using Ext.Net.MVC;
    
    @{
        ViewBag.Title = "Desktop Drag & Drop Example";
        Layout = null;
        var X = Html.X();
    
        List<MenuItem> startMenu = new List<Ext.Net.MenuItem>();
    
        var dragSourceList = new List<DragSource.Builder>();
    
        foreach (var menuEntry in new[]
        {
            new { mid = "EU", mnm = "European Union", mic = Icon.FlagEuropeanunion },
            new { mid = "US", mnm = "United States", mic = Icon.FlagUs }
        })
        {
            startMenu.Add(new MenuItem()
            {
                ID = menuEntry.mid,
                Icon = menuEntry.mic,
                Text = menuEntry.mnm
            });
    
            dragSourceList.Add(X.DragSource()
                .Target(menuEntry.mid)
                .IsTarget(false)
                .Group("desktopDD")
                .StartDrag(a => a.Fn = "App.ddOverrides.startDrag")
                .OnDragEnter(a => a.Fn = "App.ddOverrides.onDragEnter")
                .OnDragOut(a => a.Fn = "App.ddOverrides.onDragOut")
                .OnInvalidDrop(a => a.Fn = "App.ddOverrides.invalidateDrop")
                .EndDrag(a => a.Fn = "App.ddOverrides.endDrag")
            );
        }
        //startMenu.Add(new Ext.Net.MenuItem() { ID = "EU", Icon = Icon.FlagEuropeanunion, Text = "European Union"});
        //startMenu.Add(new Ext.Net.MenuItem() { ID = "US", Icon = Icon.FlagUs, Text = "United States" });
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <title>Ext.NET MVC Test Case</title>
    
        <style>
            .dropOK {
                background-color: #99ff99 !important;
            }
    
            .dropNotOK {
                border: 1px solid #FF0000 !important;
            }
        </style>
    
        <script type="text/javascript">
            Ext.onReady(function () {
                console.log("onReady");
                console.log("EU", Ext.getCmp("EU"));
                console.log("dataview-1030", Ext.getCmp("dataview-1030"));
            });
    
            function desktopReady() {
                console.log("desktopReady");
                console.log("EU", Ext.getCmp("EU"));
                console.log("dataview-1030", Ext.getCmp("dataview-1030"));
            }
    
            Ext.ns("App").ddOverrides = {
                // Called the instant the element is dragged.
                startDrag: function () {
                    console.log("startDrag");
                    // Cache the drag "phantom" element
                    if (!this.dEl) {
                        this.dEl = Ext.get(this.getDragEl());
                    }
    
                    // Cache the original element
                    if (!this.el) {
                        this.el = Ext.get(this.getEl());
                    }
    
                    // Make the original icon less visible to indicate it is really about to be moved
                    this.el.applyStyles({ opacity: 0.4 });
    
                    this.dEl.applyStyles({
                        border: "",
                        // Trim the sides to 8 pixels to have it match the icons
                        width: (this.el.getWidth() - 8) + "px",
                        height: (this.el.getHeight() - 8) + "px",
                        "z-index": 2000
                    });
    
                    // Create an exact copy of the element on the cursor
                    this.dEl.update(this.el.dom.innerHTML);
    
                    // adding this class is the trick to have drop areas to work
                    // If you just avoid this and then use this.el.dom.outerHTML above, the mouse will
                    // be always above the div and will never trigger an dropEnter event.
                    this.dEl.addCls(this.el.dom.className);
    
                    this.lastTarget = null;
                },
    
                invalidateDrop: function () {
                    this.invalidDrop = true;
                },
    
                // Called when the drag operation completes
                endDrag: function () {
                    console.log("endDrag");
                    // Create the animation configuration object
                    var animCfgObj = {
                        easing: 'ease',
                        duration: 500,
                        opacity: 1,
                        scope: this,
                    };
    
                    var success = !this.invalidDrop;
                    delete this.invalidDrop;
    
                    // Remove the drag/drop effects on the original element
                    this.el.removeCls('dropOK');
                    this.el.applyStyles({ opacity: 1 });
    
                    // Invoke the animation according to the drop success/failure
                    if (success) {
                        // After dragging, remove transparency effect of moved element.
                        this.el.animate(animCfgObj);
                        this.dEl.animate({
                            easing: 'ease',
                            duration: 2500,
                            opacity: 0.1, // left by purpose to see the hiding work
                            scope: this,
                            callback: function () { this.dEl.hide(); }
                        });
    
                        console.log('success end drag');
                    } else {
                        console.log('failure end drag');
    
                        this.dEl.hide();
                    }
    
                    return success;
                },
    
                // Only called when the drag element is dragged over the a drop target with the same ddgroup
                onDragEnter: function (evtObj, targetElId) {
                    console.log("onDragEnter");
                    // Colorize the drag target if the drag node's parent is not the same as the drop target
                    // and is valid for the car type
                    if (targetElId != this.el.dom.parentNode.id) {
                        this.el.addCls('dropOK');
                        this.dEl.addCls('dropOK');
                        this.lastTarget = Ext.get(targetElId);
                    } else {
                        // Remove the invitation
                        this.onDragOut();
                        this.lastTarget = null;
                    }
                },
    
                // Only called when element is dragged out of a dropzone with the same ddgroup
                onDragOut: function (evtObj, targetElId) {
                    console.log("onDragOut");
                    this.el.removeCls('dropOK');
                    this.dEl.removeCls('dropOK');
                    this.lastTarget = null;
                },
    
                notifyDrop: function (dd, e, data) {
                    console.log('notify drop');
    
                    return true;
                }
            };
        </script>
    </head>
    
    <body>
        @Html.X().ResourceManager()
    
        @(Html.X().Desktop()
            .ID("_nelisDesktop").Listeners(l => l.Ready.Fn = "desktopReady")
            .DesktopConfig(
                Html.X().DesktopConfig()
                .ID("_nelisDesktop_Area1")
                .SortShortcuts(true)
                    .WallpaperStretch(true)
                    .ShortcutDragSelector(true)
            )
            .StartMenu(
                Html.X().DesktopStartMenu()
                    .ID("_nelisDesktop_StartMenu")
                    .Title("Allegro Desktop")
                    .Icon(Icon.Application)
                    .MenuItems(startMenu)
                    .ToolConfig(
                        Html.X().Toolbar()
                            .Width(100)
                            .Items(
                                Html.X().Button()
                                .Icon(Icon.Calculator)
                                .Text("Calculator")
                            )
                    )
            )
            .TaskBar(
                Html.X().DesktopTaskBar()
                    .TrayWidth(40)
                    .QuickStartWidth(75)
                    .QuickStart(
                        Html.X().Toolbar()
                            .Items(
                                Html.X().Button()
                                    .Icon(Icon.ApplicationTileVertical)
                                    .ToolTip("Tile windows")
                                    .OverflowText("Tile windows"),
                                Html.X().Button()
                                    .Icon(Icon.ApplicationCascade)
                                    .ToolTip("Cascade windows")
                                    .OverflowText("Cascade windows"),
                                Html.X().Button()
                                    .Icon(Icon.ApplicationViewIcons)
                                    .ToolTip("Default icons positions")
                            )
                    )
            )
            .Modules(
                Html.X().DesktopModule().ModuleID("Notepad").Shortcut(new DesktopShortcut { Name = "Notepad", IconCls = "x-notepad-shortcut" })
            )
        )
    
        @(X.Container()
            .ID("dragSourceHolder")
        )
    
        @{
            foreach (var dds in dragSourceList)
            {
                @(dds)
            }
        }
    
        @(X.DropZone()
            .Target("_nelisDesktop_Area1-body")
            .Group("desktopDD")
            .IsTarget(true)
            .OnContainerDrop(a => a.Fn = "App.ddOverrides.onDrop")
            .NotifyDrop(a=> a.Fn = "App.ddOverrides.notifyDrop")
            .OnNodeDrop(a => a.Fn = "App.ddOverrides.nodeDrop")
        )
    </body>
    </html>
    I hope this helps!
    Last edited by fabricio.murta; Sep 12, 2017 at 8:28 PM.
  5. #5
    Hi FabrÃ*cio,
    thank you for your assistance and code you provided. After testing your example I have one question. Is it correct and standard behaviour that - in order to drag & drop an item - you have to click twice? On left mouse click, I start dragging... no event is triggered. I release a button... now are startDrag and onDragEnter events fired... I push a button again and only now are notifyDrop, onDragOut and endDrag events fired.

    I'm quite confused from such events order. If it works as designed... I'm afraid that I will need to look for a more user-friendly solution. Thank you for your opinion.

    Dan
  6. #6
    Hello Dan!

    I don't have the behavior you are describing. Tested the example I provided using both Google Chrome and MS Edge. I click to expand the start menu, then click dragging the EU (or US) icon, and it just follows, changing colors as I drag over the draggable area. No need to "click-to-focus + click-to-drag" at all.

    There may be something else on your project, please give it a try on a fresh project. Ensure you are using latest Ext.NET version, the provided code sample was expanded under Ext.NET 4.4.0.
    Fabrício Murta
    Developer & Support Expert
  7. #7
    I'm not sure the forum will allow playing the .gif animation, but here's a try, reproducing the example. No double click happened at any point.

    Attachment 25040

    EDIT: Well, sorry, it does not allow gif sharing.

    EDIT2: this should do it: 62106-desktopDD.gif
    Attached Thumbnails Click image for larger version. 

Name:	62106-desktopDD.jpg 
Views:	64 
Size:	12.8 KB 
ID:	25041  
    Last edited by fabricio.murta; Sep 13, 2017 at 12:11 AM.
  8. #8
    Hi FabrÃ*cio,
    thank you for your effort. The test cases I provide are always created outside the main project in a completely clean environment. In that case, there was a problem with Ext.NET installed... I was a minor version behind (mea culpa, mea maxima culpa). After an update, everything works as expected.

    Thank you very much for your valuable help. The thread can be closed.

    Dan
  9. #9
    Hello, @NewLink!

    Glad it helped! I wouldn't expect also this to be an issue in just one version behind but we can't replay test cases in every prior version once one is publicly released. It was really a coincidence this issue happened in 4.3.0 whilst working in 4.4.0.

    Anyway, thanks for the feedback, and glad it works for you now!
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. Replies: 1
    Last Post: Oct 01, 2012, 5:29 PM
  2. Replies: 8
    Last Post: Jul 29, 2012, 10:58 AM
  3. Drag Drop Not to Remove The Item In The Dragzone
    By hyq01221987 in forum 1.x Help
    Replies: 0
    Last Post: Mar 18, 2012, 5:24 AM
  4. [CLOSED] menu item drag and drop
    By SymSure in forum 1.x Legacy Premium Help
    Replies: 10
    Last Post: Apr 18, 2011, 7:03 PM
  5. access to item of menu in Coolite desktop
    By mono in forum 1.x Help
    Replies: 0
    Last Post: Aug 10, 2009, 11:50 AM

Tags for this Thread

Posting Permissions