This is a migrated thread and some comments may be shown as answers.

Docks dynamically loading custom controls from DB when Dragged & Dropped... almost working :)

1 Answer 110 Views
Dock
This is a migrated thread and some comments may be shown as answers.
Christophe
Top achievements
Rank 1
Christophe asked on 20 Apr 2012, 02:38 AM
Hi there,

What I'm trying to achieve here is I think pretty simple and is nearly working. I have a RadGrid with drag and drop set to true, an extender so I can design my own helper when dragging and a RadDock drop zone.
I followed this example to load Custom WebControls dynamically in my docks, this one for virtual scrolling in my grid, and been sent this project sample to drag and drop nodes from TreeView to a dockzone few weeks ago by the Telerik team (Thanks again ;)).

It works fine if I'm not using the ASP UpdatePanel for AsyncPostback except that when I add a new dock to my zone or re-order them, all the pre-existing docks become empty. I first thought that this was due to the fact that I'm not posting my data properly using this UpdatePanel and thus implemented it.

I'm now getting an error saying that it couldn't find my UpdatePanel1 :

PRM_MissingPanel : Could not find UpdatePanel with ID UpdatePanel1.

Here's my code, hopefully someone will be able to help. I'm suspecting the RadAjaxPanel embedding the UpdatePanel to screw this up, but I kinda need it to pass some parameters my method in code behind:

ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="StopsMgr.aspx.cs" Inherits="Test.StopsMgr" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head runat="server">
    <title>Stop Manager</title>
    <link href="css/StopsMgr.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <telerik:RadScriptManager ID="RadScriptManager1" runat="server">
        <Scripts>
            <%--Needed for JavaScript IntelliSense in VS2010--%>
            <%--For VS2008 replace RadScriptManager with ScriptManager--%>
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" />
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" />
        </Scripts>
    </telerik:RadScriptManager>
    <div id="TabStop">
        <telerik:RadAjaxLoadingPanel ID="StopLoadingPanel" runat="server">
        </telerik:RadAjaxLoadingPanel>
        <telerik:RadCodeBlock ID="RadCodeBlock_StopScript" runat="server">
            <script type="text/javascript">
                function showLoadingPanel(sender, args) {
                    toggleLoadingPanel(sender.get_id(), true);
                }
 
                function hideLoadingPanel(sender, args) {
                    toggleLoadingPanel(sender.get_id(), false);
                }
 
                function toggleLoadingPanel(elementId, show) {
                    var loadingPanel = $find("StopLoadingPanel");
                    if (show) {
                        loadingPanel.show(elementId);
                    }
                    else {
                        loadingPanel.hide(elementId);
                    }
                }
 
                function clientDragCreating(sender, args) {
                    var grid = $find("<%=GridSearchStops.ClientID %>");
                    var MasterTable = grid.get_masterTableView();
                    var selectedRows = MasterTable.get_selectedItems();
                    var name = MasterTable.getCellByColumnUniqueName(selectedRows[0], "Name");
                    var lines = MasterTable.getCellByColumnUniqueName(selectedRows[0], "Lines");
 
                    $("#rgDraggedItemHeader").html(name.innerHTML);
                    $("#rgDraggedItemSub").html(lines.innerHTML);
                }
 
                var currentGrid;
                var zone;
                var mouseX;
                var mouseY;
                var displayPlaceholder = false;
                function onRowDragStarted(sender, args) {
                    currentGrid = sender;
                    zone = $find("RadDockZoneStops");
 
                    $(document).mousemove(function (e) {
                        mouseX = e.pageX;
                        mouseY = e.pageY;
                        if (zone != null && displayPlaceholder)
                            zone._showPlaceholder(args.get_gridDataItem());
                    });
                    $("#RadDockZoneStops").mouseenter(function () {
                        displayPlaceholder = true;
                    }).mouseleave(function () {
                        displayPlaceholder = false;
                        if (zone != null)
                            zone._hidePlaceholder();
                    });
                }
 
                function onRowDropping(sender, args) {
                    zone = $find("RadDockZoneStops");
                    if (zone != null)
                        zone._hidePlaceholder();
                    $(document).unbind('mousemove');
                    $("#RadDockZoneStops").unbind('mouseenter').unbind('mouseleave');
                    if (sender.get_id() == "<%=GridSearchStops.ClientID %>") {
                        var node = args.get_destinationHtmlElement();
                        if (isChildOf('RadDockZoneStops', node)) {
 
                            $find("<%= RadAjaxPanel1.ClientID%>").ajaxRequestWithTarget("<%= RadAjaxPanel1.UniqueID %>", "LoadDock¤" + args._dragedItems[0].getDataKeyValue('Id'));
                             
                            args.set_cancel(true);
                        }
                    }
                    args.set_cancel(true);
                }
 
                function isChildOf(parentId, element) {
                    while (element) {
                        if (element.id && element.id.indexOf(parentId) > -1) {
                            return true;
                        }
                        element = element.parentNode;
                    }
                    return false;
                }
            </script>
        </telerik:RadCodeBlock>
        <div id="Search">
            <telerik:RadGrid ID="GridSearchStops" runat="server" AllowPaging="true" PageSize="42"
                AutoGenerateColumns="false" Height="820px" >
                <PagerStyle Mode="NextPrevNumericAndAdvanced" />
                <MasterTableView TableLayout="Fixed" DataKeyNames="Id" ClientDataKeyNames="Id">
                    <Columns>
                        <telerik:GridBoundColumn DataField="Id" HeaderText="ID" />
                        <telerik:GridBoundColumn DataField="Name" HeaderText="Stop Name" />
                        <telerik:GridBoundColumn DataField="Lines" HeaderText="Currently On Lines" />
                    </Columns>
                </MasterTableView>
                <ClientSettings AllowRowsDragDrop="true">
                    <Scrolling AllowScroll="true" EnableVirtualScrollPaging="true" UseStaticHeaders="true" />
                    <DataBinding Location="StopsMgr.aspx" SelectMethod="GetStopData" SelectCountMethod="GetStopCount"
                        StartRowIndexParameterName="startRowIndex" MaximumRowsParameterName="maxRows" />
                    <ClientEvents OnCommand="showLoadingPanel" OnDataBound="hideLoadingPanel" OnRowDragStarted="onRowDragStarted"
                        OnRowDropping="onRowDropping" />
                    <Selecting AllowRowSelect="true" />
                </ClientSettings>
            </telerik:RadGrid>
            <ext:GridCustomDragExtender ID="GridCustomDragExtender1" runat="server" TargetControlID="GridSearchStops"
                CursorOffsetLeft="0" CursorOffsetTop="0" OnClientDragContentCreating="clientDragCreating">
                <DragContentTemplate>
                    <div class="rgDraggedItem">
                        <div id="rgDraggedItemHeader">
                        </div>
                        <div id="rgDraggedItemSub">
                        </div>
                    </div>
                </DragContentTemplate>
            </ext:GridCustomDragExtender>
        </div>
        <div id="DropZone">
            <input type="text" id="currentPlaceholderPosition" runat="server" style="display: none" />
            <telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server" OnAjaxRequest="OnAjaxRequest_Action">
                <telerik:RadDockLayout ID="RadDockLayout1" runat="server" OnLoadDockLayout="RadDockLayout1_LoadDockLayout"
                    OnSaveDockLayout="RadDockLayout1_SaveDockLayout">
                    <telerik:RadDockZone ID="RadDockZoneStops" runat="server" MinHeight="300px" HighlightedCssClass="RadDockZoneStopsHighlight">
                    </telerik:RadDockZone>
                    <div style="display: none">
                        Hidden UpdatePanel, which is used to receive the new dock controls. We will move
                        them with script to the desired initial dock zone.
                        <asp:UpdatePanel runat="server" ID="UpdatePanel1">
                            <Triggers>
                                <asp:AsyncPostBackTrigger ControlID="GridSearchStops" EventName="RowDrop" />
                            </Triggers>
                        </asp:UpdatePanel>
                    </div>
                </telerik:RadDockLayout>
            </telerik:RadAjaxPanel>
        </div>
    </div>
    <script type="text/javascript">
        var $T = Telerik.Web.UI;
        var isRowDragged = false;
 
        //parameter can be dock or GridDataItem
        Telerik.Web.UI.RadDockZone.prototype._showPlaceholder = function (obj, location) {
            if (Object.getTypeName(obj) == "Telerik.Web.UI.GridDataItem") {
                isRowDragged = true;
                var row = obj;
                this._repositionPlaceholder(row.get_element(), location);
                var placeholderStyle = this._placeholder.style;
                placeholderStyle.height = "50px";
                placeholderStyle.width = "100%";
                placeholderStyle.display = "block";
                isRowDragged = false;
            }
            else {
                var dock = obj;
                this._repositionPlaceholder(dock.get_element(), location);
                var dockBounds = dock._getBounds();
                var placeholderMargin = dock._getMarginBox(this._placeholder);
                var placeholderBorder = dock._getBorderBox(this._placeholder);
                var horizontal = this.get_isHorizontal();
                var placeholderStyle = this._placeholder.style;
                placeholderStyle.height = dockBounds.height - (placeholderMargin.vertical + placeholderBorder.vertical) + "px";
                placeholderStyle.width = this.get_fitDocks() && !horizontal ? "100%" : dockBounds.width - (placeholderMargin.horizontal + placeholderBorder.horizontal) + "px";
                placeholderStyle.display = "block";
            }
        }
 
        Telerik.Web.UI.RadDockZone.prototype._repositionPlaceholder = function (dock_element, location) {
            //fix Row drag  
            if (isRowDragged == true) {
                location = new Sys.UI.Point(mouseX, mouseY);
            }
            //end fix  
 
            var nearestChild = this._findItemAt(location, dock_element);
 
            var zone_element = this.get_element();
 
            if (null == nearestChild) {
                // _clearElement must be after all docks and _placeholder
                zone_element.insertBefore(this._placeholder, this._clearElement);
            }
            else {
                if (nearestChild.previousSibling != this._placeholder) {
                    zone_element.insertBefore(this._placeholder, nearestChild);
                }
            }
            //GET placeholder position  
            for (var i = 0; i < zone_element.childNodes.length; i++) {
                if (zone_element.childNodes[i] == this._placeholder) {
                    var currentPos = i;
                    $get('currentPlaceholderPosition').value = currentPos - 2;
                }
            }
            //end Get
        }        
    </script>
    </form>
</body>
</html>

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Data;
using Telerik.Web.UI;
 
namespace test
{
    public partial class StopsMgr : System.Web.UI.Page
    {
 
        private List<DockState> CurrentDockStates
        {
            get
            {
                //Store the info about the added docks in the session. For real life
                // applications we recommend using database or other storage medium
                // for persisting this information.
                List<DockState> _currentDockStates = (List<DockState>)Session["CurrentDockStatesDynamicDocks"];
                if (Object.Equals(_currentDockStates, null))
                {
                    _currentDockStates = new List<DockState>();
                    Session["CurrentDockStatesDynamicDocks"] = _currentDockStates;
                }
                return _currentDockStates;
            }
            set
            {
                Session["CurrentDockStatesDynamicDocks"] = value;
            }
        }
 
        private RadDock CreateRadDockFromState(DockState state)
        {
            RadDock dock = new RadDock();
            dock.ID = string.Format("RadDock{0}", state.UniqueName);
             
            dock.ApplyState(state);
            dock.Command += new DockCommandEventHandler(dock_Command);
            dock.Commands.Add(new DockCloseCommand());
            dock.Commands.Add(new DockExpandCollapseCommand());
 
            return dock;
        }
 
        protected void Page_Init(object sender, EventArgs e)
        {
            //Recreate the docks in order to ensure their proper operation
            for (int i = 0; i < CurrentDockStates.Count; i++)
            {
                RadDock dock = CreateRadDockFromState(CurrentDockStates[i]);
                //We will just add the RadDock control to the RadDockLayout.
                // You could use any other control for that purpose, just ensure
                // that it is inside the RadDockLayout control.
                // The RadDockLayout control will automatically move the RadDock
                // controls to their corresponding zone in the LoadDockLayout
                // event (see below).
                RadDockLayout1.Controls.Add(dock);
                //We want to save the dock state every time a dock is moved.
                CreateSaveStateTrigger(dock);
            }
        }
 
        protected void Page_Load(object sender, EventArgs e)
        {
            //this.DataBind();
        }
 
        #region Stops
 
        [WebMethod]
        public static int GetStopCount()
        {
            var cmd = new SqlCommand("P_GetNumberOfStops", new SqlConnection(WebConfigurationManager.ConnectionStrings["TestDB"].ConnectionString));
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection.Open();
            if (cmd.Connection.State != ConnectionState.Open)
                throw new Exception("Connection to DB failed");
 
            var max = (int)cmd.ExecuteScalar();
            cmd.Connection.Close();
            return max;
        }
 
        [WebMethod]
        public static IEnumerable<Stop> GetStopData(int startRowIndex, int maxRows)
        {
            var cmd = new SqlCommand("P_GetStopData", new SqlConnection(WebConfigurationManager.ConnectionStrings["TestDB"].ConnectionString));
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@startRow", SqlDbType.Int));
            cmd.Parameters.Add(new SqlParameter("@maxRows", SqlDbType.Int));
            cmd.Parameters["@startRow"].Value = startRowIndex;
            cmd.Parameters["@maxRows"].Value = startRowIndex + maxRows;
 
            cmd.Connection.Open();
            if (cmd.Connection.State != ConnectionState.Open)
                throw new Exception("Connection to DB failed");
 
            var sqlRd = cmd.ExecuteReader();
            if (sqlRd.HasRows)
            {
                while (sqlRd.Read())
                {
                    var stop = new Stop()
                    {
                        Id = (int)sqlRd["S_ID"],
                        Name = sqlRd["S_NAME"].ToString(),
                        Lines = "---"
                    };
 
                    yield return stop;
                }
            }
            cmd.Connection.Close();
        }
 
        #region DockPanel
 
        void dock_Command(object sender, DockCommandEventArgs e)
        {
            if (e.Command.Name == "Close")
            {
                ScriptManager.RegisterStartupScript(
                UpdatePanel1,
                this.GetType(),
                "RemoveDock",
                string.Format(@"function _removeDock() {{ 
                                Sys.Application.remove_load(_removeDock); 
                                $find('{0}').undock(); 
                                $get('{1}').appendChild($get('{0}')); 
                                $find('{0}').doPostBack('DockPositionChanged'); 
                                }}; 
                                Sys.Application.add_load(_removeDock);", ((RadDock)sender).ClientID, UpdatePanel1.ClientID),
                              true);
 
            }
        }
 
        private void CreateSaveStateTrigger(RadDock dock)
        {
            //Ensure that the RadDock control will initiate postback
            // when its position changes on the client or any of the commands is clicked.
            //Using the trigger we will "ajaxify" that postback.
            dock.AutoPostBack = true;
            dock.CommandsAutoPostBack = true;
 
            AsyncPostBackTrigger saveStateTrigger = new AsyncPostBackTrigger();
            saveStateTrigger.ControlID = dock.ID;
            saveStateTrigger.EventName = "DockPositionChanged";
            UpdatePanel1.Triggers.Add(saveStateTrigger);
 
            saveStateTrigger = new AsyncPostBackTrigger();
            saveStateTrigger.ControlID = dock.ID;
            saveStateTrigger.EventName = "Command";
            UpdatePanel1.Triggers.Add(saveStateTrigger);
        }
 
        protected void RadDockLayout1_LoadDockLayout(object sender, DockLayoutEventArgs e)
        {
            //Populate the event args with the state information. The RadDockLayout control
            // will automatically move the docks according that information.
            foreach (DockState state in CurrentDockStates)
            {
                e.Positions[state.UniqueName] = state.DockZoneID;
                e.Indices[state.UniqueName] = state.Index;
            }
        }
 
        protected void RadDockLayout1_SaveDockLayout(object sender, DockLayoutEventArgs e)
        {
            //Save the dock state in the page Session. This will enable us
            // to recreate the dock in the next Page_Init.
            CurrentDockStates = RadDockLayout1.GetRegisteredDocksState();
        }
 
        protected void OnAjaxRequest_Action(object sender, AjaxRequestEventArgs e)
        {
            var args = e.Argument.Split('¤');
            if (args[0] == "LoadDock" && args.Length > 1)
            {
                var dock = LoadDock(int.Parse(args[1]));
                var currentPos = int.Parse(currentPlaceholderPosition.Value);
                UpdatePanel1.ContentTemplateContainer.Controls.Add(dock);
 
 
                ScriptManager.RegisterStartupScript(
                dock,
                this.GetType(),
                "AddDock",
                string.Format(@"function _addDock() {{ 
                                Sys.Application.remove_load(_addDock); 
                                $find('{1}').dock($find('{0}'),{2});  
                                $find('{0}').doPostBack('DockPositionChanged'); 
                                }}; 
                                Sys.Application.add_load(_addDock);", dock.ClientID, RadDockZoneStops.ID, currentPos),
                            true);
 
                CreateSaveStateTrigger(dock);
            }
        }
 
        private RadDock LoadDock(int id)
        {
            try
            {
                var dock = new RadDock();
 
                dock.DockMode = DockMode.Docked;
                dock.EnableRoundedCorners = true;
                dock.UniqueName = Guid.NewGuid().ToString();
                dock.ID = string.Format("RadDock{0}", dock.UniqueName);
                dock.Title = "Title " + id;
                var widget = LoadControl(this, "~/Templates/StopFormTpl.ascx", id, "myTitle");
                widget.EnableViewState = false;
                dock.ContentContainer.Controls.Add(widget);
                dock.Width = Unit.Percentage(100);
                dock.Height = Unit.Pixel(200);
                dock.Commands.Add(new DockCloseCommand());
                dock.Commands.Add(new DockExpandCollapseCommand());
                dock.Command += new DockCommandEventHandler(dock_Command);
 
                return dock;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex.InnerException);
            }
        }

When, I refresh the page, the dock appears but is not docked to the zone.

Help anyone ?

Cheers

1 Answer, 1 is accepted

Sort by
0
Christophe
Top achievements
Rank 1
answered on 20 Apr 2012, 03:02 AM
SOLVED !!!

It was as easy as moving the RadDockLayout out of the RadAjaxPanel. I don't know why I didn't think of that earlier... ;)

    <telerik:RadDockLayout ID="RadDockLayout1" runat="server" OnLoadDockLayout="RadDockLayout1_LoadDockLayout"
        OnSaveDockLayout="RadDockLayout1_SaveDockLayout">
        <telerik:RadDockZone ID="RadDockZoneStops" runat="server" MinHeight="300px" HighlightedCssClass="RadDockZoneStopsHighlight">
        </telerik:RadDockZone>
        <div style="display: none">
            <asp:UpdatePanel runat="server" ID="UpdatePanel1">
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="GridSearchStops" EventName="RowDrop" />
                </Triggers>
            </asp:UpdatePanel>
        </div>
    </telerik:RadDockLayout>
<telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server" OnAjaxRequest="OnAjaxRequest_Action">
</telerik:RadAjaxPanel>
Tags
Dock
Asked by
Christophe
Top achievements
Rank 1
Answers by
Christophe
Top achievements
Rank 1
Share this question
or