Originally Posted by
vadym.f
Hi guys,
Below is the complete code sample utilizing the drag-and-drop paradigm doubled up by the button controls. Now, with the tune-up you've suggested, performance of sizable drag-and-drop operations seems OK. What's strangely lagging behind is moving one or several items across the grid panels using the buttons. Please select one or more items anywhere on either grid and hit the > or < button to observe the issue. I'm not sure what makes it so inefficient. Could it be the call to getSelectionModel().getSelections() ?
<%@ Page Language="C#" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<%@ Import Namespace="System.Data" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.StoreLeft.DataSource = GetAddress(1000);
this.StoreLeft.DataBind();
this.StoreRight.DataBind();
this.ButtonOneRight.Disabled = true;
this.ButtonOneLeft.Disabled = true;
}
}
private static IEnumerable<object> GetAddress(int count)
{
for (int i = 0; i < count; i++)
{
yield return
new
{
AddressID = "AddressID_" + i,
Address1 = "Line1_" + i,
AdressLine2 = "Line2_" + i,
City = "City_" + i,
ZIP = "M6Y OP9",
Province = "Province",
Country = "Country"
};
}
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Overview of MultiSelect - Ext.NET Examples</title>
<ext:XScript ID="XScript1" runat="server">
<script type="text/javascript" language="javascript">
var recordIconRenderer = function (value, metadata, record) {
var iconSrc = Ext.net.ResourceMgr.getIconUrl("Note");
return String.format("<img src='{0}' />", iconSrc);
};
var fromLeftToRight = function () {
fromTo(#{GridPanelLeft}, #{GridPanelRight});
#{ButtonOneRight}.disable();
#{ButtonAllLeft}.enable();
if(#{GridPanelLeft}.store.getTotalCount()==0)
#{ButtonAllRight}.disable();
};
var fromRightToLeft = function () {
fromTo(#{GridPanelRight}, #{GridPanelLeft});
#{ButtonOneLeft}.disable();
#{ButtonAllRight}.enable();
if(#{GridPanelRight}.store.getTotalCount()==0)
#{ButtonAllLeft}.disable();
};
var allFromLeftToRight = function () {
moveAll(#{GridPanelLeft}, #{GridPanelRight});
#{ButtonOneRight}.disable();
#{ButtonAllRight}.disable();
#{ButtonAllLeft}.enable();
};
var allFromRightToLeft = function () {
moveAll(#{GridPanelRight}, #{GridPanelLeft});
#{ButtonOneLeft}.disable();
#{ButtonAllLeft}.disable();
#{ButtonAllRight}.enable();
};
var moveAll = function (fromGrid, toGrid) {
// var records = fromGrid.store.getRange();
var records = fromGrid.store.getAllRange();
fromGrid.store.suspendEvents(false);
toGrid.store.suspendEvents(false);
fromGrid.store.removeAll(true);
toGrid.store.add(records);
fromGrid.store.resumeEvents();
toGrid.store.resumeEvents();
fromGrid.getView().refresh();
toGrid.getView().refresh();
return true;
}
var fromTo = function (fromGrid, toGrid) {
var records = fromGrid.getSelectionModel().getSelections();
fromGrid.store.suspendEvents(false);
toGrid.store.suspendEvents(false);
fromGrid.store.remove(records);
toGrid.store.add(records);
fromGrid.store.resumeEvents();
toGrid.store.resumeEvents();
fromGrid.getView().refresh();
toGrid.getView().refresh();
return true;
};
var notifyDropToLeft = function (ddSource, e, data) {
var records=data.selections;
ddSource.grid.store.suspendEvents(false);
#{StoreLeft}.suspendEvents(false);
ddSource.grid.store.remove(records);
#{StoreLeft}.add(records);
ddSource.grid.store.resumeEvents();
#{StoreLeft}.resumeEvents();
#{ButtonOneLeft}.disable();
#{ButtonAllRight}.enable();
if(#{GridPanelRight}.store.getTotalCount()==0)
#{ButtonAllLeft}.disable();
#{GridPanelLeft}.getView().refresh();
#{GridPanelRight}.getView().refresh();
return true;
};
var notifyDropToRight = function (ddSource, e, data) {
var records=data.selections;
ddSource.grid.store.suspendEvents(false);
#{StoreRight}.suspendEvents(false);
ddSource.grid.store.remove(records);
#{StoreRight}.add(records);
ddSource.grid.store.resumeEvents();
#{StoreRight}.resumeEvents();
#{ButtonOneRight}.disable();
#{ButtonAllLeft}.enable();
if(#{GridPanelLeft}.store.getTotalCount()==0)
#{ButtonAllRight}.disable();
#{GridPanelLeft}.getView().refresh();
#{GridPanelRight}.getView().refresh();
return true;
};
</script>
</ext:XScript>
</head>
<body>
<form id="Form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" />
<ext:Store ID="StoreLeft" runat="server">
<Reader>
<ext:JsonReader IDProperty="AddressID">
<Fields>
<ext:RecordField Name="AddressID" SortDir="ASC" />
<ext:RecordField Name="Address1" />
<ext:RecordField Name="Address2" />
<ext:RecordField Name="City" />
<ext:RecordField Name="ZIP" />
<ext:RecordField Name="Province" />
<ext:RecordField Name="Country" />
</Fields>
</ext:JsonReader>
</Reader>
<Listeners>
<Remove Handler="#{ButtonAllLeft}.enable();
#{ButtonOneRight}.disable();
#{ButtonOneLeft}.disable();
if(this.getTotalCount()==0)
#{ButtonAllRight}.disable();
else
#{ButtonAllRight}.enable();" />
</Listeners>
</ext:Store>
<ext:Store ID="StoreRight" runat="server">
<Reader>
<ext:JsonReader IDProperty="AddressID">
<Fields>
<ext:RecordField Name="AddressID" SortDir="ASC" />
<ext:RecordField Name="Address1" />
<ext:RecordField Name="Address2" />
<ext:RecordField Name="City" />
<ext:RecordField Name="ZIP" />
<ext:RecordField Name="Province" />
<ext:RecordField Name="Country" />
</Fields>
</ext:JsonReader>
</Reader>
<Listeners>
<Remove Handler="#{ButtonAllRight}.enable();
#{ButtonOneRight}.disable();
#{ButtonOneLeft}.disable();
if(this.getTotalCount()==0)
#{ButtonAllLeft}.disable();
else
#{ButtonAllLeft}.enable();" />
</Listeners>
</ext:Store>
<ext:Panel ID="Panel13" runat="server" Title="Drag/Drop (Insert Mode)" Padding="10">
<Items>
<ext:TableLayout ID="TableLayout5" runat="server" Columns="3">
<Cells>
<ext:Cell>
<ext:Panel ID="Panel14" runat="server" Layout="FitLayout" Border="true" BodyStyle="height: 260px;"
Title="Available Items">
<Items>
<ext:GridPanel ID="GridPanelLeft" runat="server" EnableDragDrop="true" DDGroup="GridPanelRightDDGroup"
Width="560" Height="250" StoreID="StoreLeft" Frame="false" Border="true" StripeRows="true"
TrackMouseOver="true" ActiveIndex="0" SelectionMemory="Enabled" Split="true"
AutoScroll="true">
<ColumnModel runat="server" ID="ColumnModel1">
<Columns>
<ext:Column ColumnID="IconColumn" MenuDisabled="true" Sortable="false" Resizable="false"
Hideable="false" Width="26">
<Renderer Fn="recordIconRenderer" />
</ext:Column>
<ext:Column ColumnID="AddressID" Header="AddressID" DataIndex="AddressID"
Hidden="true" />
<ext:Column ColumnID="Address1" Header="Address Line1" DataIndex="Address1"
Width="140" />
<ext:Column ColumnID="Address2" Header="Address Line2" DataIndex="Address2"
Width="130" />
<ext:Column ColumnID="City" Header="City" DataIndex="City" Width="80" />
<ext:Column ColumnID="ZIP" Header="Postal Code" DataIndex="ZIP" Width="80">
</ext:Column>
<ext:Column ColumnID="Province" Header="Province" DataIndex="Province"
Width="80" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel runat="server" SingleSelect="false" ID="RowSelectionModel1">
</ext:RowSelectionModel>
</SelectionModel>
<LoadMask ShowMask="true" />
<Listeners>
<RowClick Handler="#{ButtonOneRight}.enable();" />
<RowDblClick Handler="fromLeftToRight();" />
</Listeners>
</ext:GridPanel>
</Items>
</ext:Panel>
</ext:Cell>
<ext:Cell>
<ext:Panel ID="Panel1" runat="server" Border="false" Layout="VBoxLayout" BodyStyle="height: 300px;">
<Defaults>
<ext:Parameter Name="margins" Value="5 0 5 0" Mode="Value" />
</Defaults>
<LayoutConfig>
<ext:VBoxLayoutConfig Padding="5" Align="Center" Pack="Center" />
</LayoutConfig>
<Items>
<ext:Button ID="ButtonOneRight" runat="server" Icon="ResultsetNext" Width="30">
<Listeners>
<Click Handler="fromLeftToRight();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip4" runat="server" Title="Add" Html="<nobr>Add Selected Items</nobr>" />
</ToolTips>
</ext:Button>
<ext:Button ID="ButtonAllRight" runat="server" Icon="ResultsetLast" Width="30">
<Listeners>
<Click Handler="allFromLeftToRight();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip3" runat="server" Title="Add all" Html="<nobr>Add All Items</nobr>" />
</ToolTips>
</ext:Button>
<ext:Button ID="ButtonOneLeft" runat="server" Icon="ResultsetPrevious" Width="30">
<Listeners>
<Click Handler="fromRightToLeft();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip2" runat="server" Title="Remove" Html="<nobr>Remove Selected Items</nobr>" />
</ToolTips>
</ext:Button>
<ext:Button ID="ButtonAllLeft" runat="server" Icon="ResultsetFirst" Width="30">
<Listeners>
<Click Handler="allFromRightToLeft();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip1" runat="server" Title="Remove all" Html="<nobr>Remove All Items</nobr>" />
</ToolTips>
</ext:Button>
</Items>
</ext:Panel>
</ext:Cell>
<ext:Cell>
<ext:Panel ID="Panel15" runat="server" Layout="FitLayout" Border="true" BodyStyle="height: 260px;"
Title="Selected Items">
<Items>
<ext:GridPanel ID="GridPanelRight" runat="server" EnableDragDrop="true" DDGroup="GridPanelLeftDDGroup"
Width="560" Height="250" StoreID="StoreRight" Frame="false" Border="true" StripeRows="true"
TrackMouseOver="true" ActiveIndex="0" SelectionMemory="Enabled" Split="true"
AutoScroll="true">
<ColumnModel runat="server" ID="ColumnModel2">
<Columns>
<ext:Column ColumnID="IconColumn" MenuDisabled="true" Sortable="false" Resizable="false"
Hideable="false" Width="26">
<Renderer Fn="recordIconRenderer" />
</ext:Column>
<ext:Column ColumnID="AddressID" Header="AddressID" DataIndex="AddressID"
Hidden="true" />
<ext:Column ColumnID="Address1" Header="Address Line1" DataIndex="Address1"
Width="140" />
<ext:Column ColumnID="Address2" Header="Address Line2" DataIndex="Address2"
Width="130" />
<ext:Column ColumnID="City" Header="City" DataIndex="City" Width="80" />
<ext:Column ColumnID="ZIP" Header="Postal Code" DataIndex="ZIP" Width="80">
</ext:Column>
<ext:Column ColumnID="Province" Header="Province" DataIndex="Province"
Width="80" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel runat="server" SingleSelect="false" ID="RowSelectionModel2">
</ext:RowSelectionModel>
</SelectionModel>
<LoadMask ShowMask="true" />
<Listeners>
<RowClick Handler="#{ButtonOneLeft}.enable();" />
<RowDblClick Handler="fromRightToLeft();" />
</Listeners>
</ext:GridPanel>
</Items>
</ext:Panel>
</ext:Cell>
</Cells>
</ext:TableLayout>
</Items>
</ext:Panel>
<ext:DropTarget ID="DropTarget1" runat="server" Target="={GridPanelLeft.view.scroller.dom}"
Group="GridPanelLeftDDGroup">
<NotifyDrop Fn="notifyDropToLeft" />
</ext:DropTarget>
<ext:DropTarget ID="DropTarget2" runat="server" Target="={GridPanelRight.view.scroller.dom}"
Group="GridPanelRightDDGroup">
<NotifyDrop Fn="notifyDropToRight" />
</ext:DropTarget>
</form>
</body>
</html>
I think the main problem is that functions call refresh methods of views. It's very expensive operation. But if you will not do refresh manually, for example if records count less than 10, then you can do moving of record via ExtJS API. Look at fromTo function:
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.StoreLeft.DataSource = GetAddress(1000);
this.StoreLeft.DataBind();
this.StoreRight.DataBind();
this.ButtonOneRight.Disabled = true;
this.ButtonOneLeft.Disabled = true;
}
}
private static IEnumerable<object> GetAddress(int count)
{
for (int i = 0; i < count; i++)
{
yield return
new
{
AddressID = "AddressID_" + i,
Address1 = "Line1_" + i,
AdressLine2 = "Line2_" + i,
City = "City_" + i,
ZIP = "M6Y OP9",
Province = "Province",
Country = "Country"
};
}
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Overview of MultiSelect - Ext.NET Examples</title>
<ext:XScript ID="XScript1" runat="server">
<script type="text/javascript" language="javascript">
var recordIconRenderer = function (value, metadata, record) {
var iconSrc = Ext.net.ResourceMgr.getIconUrl("Note");
return String.format("<img src='{0}' />", iconSrc);
};
var fromLeftToRight = function () {
fromTo(#{GridPanelLeft}, #{GridPanelRight});
#{ButtonOneRight}.disable();
#{ButtonAllLeft}.enable();
if(#{GridPanelLeft}.store.getTotalCount()==0)
#{ButtonAllRight}.disable();
};
var fromRightToLeft = function () {
fromTo(#{GridPanelRight}, #{GridPanelLeft});
#{ButtonOneLeft}.disable();
#{ButtonAllRight}.enable();
if(#{GridPanelRight}.store.getTotalCount()==0)
#{ButtonAllLeft}.disable();
};
var allFromLeftToRight = function () {
moveAll(#{GridPanelLeft}, #{GridPanelRight});
#{ButtonOneRight}.disable();
#{ButtonAllRight}.disable();
#{ButtonAllLeft}.enable();
};
var allFromRightToLeft = function () {
moveAll(#{GridPanelRight}, #{GridPanelLeft});
#{ButtonOneLeft}.disable();
#{ButtonAllLeft}.disable();
#{ButtonAllRight}.enable();
};
var moveAll = function (fromGrid, toGrid) {
// var records = fromGrid.store.getRange();
var records = fromGrid.store.getAllRange();
fromGrid.store.suspendEvents(false);
toGrid.store.suspendEvents(false);
fromGrid.store.removeAll(true);
toGrid.store.add(records);
fromGrid.store.resumeEvents();
toGrid.store.resumeEvents();
fromGrid.getView().refresh();
toGrid.getView().refresh();
return true;
}
var fromTo = function (fromGrid, toGrid) {
console.log(new Date());
var records = fromGrid.getSelectionModel().getSelections();
if (records.length > 10) {
fromGrid.store.suspendEvents(false);
toGrid.store.suspendEvents(false);
fromGrid.store.remove(records);
toGrid.store.add(records);
fromGrid.store.resumeEvents();
toGrid.store.resumeEvents();
fromGrid.getView().refresh();
toGrid.getView().refresh();
} else {
fromGrid.store.remove(records);
toGrid.store.add(records);
}
console.log(new Date());
return true;
};
var notifyDropToLeft = function (ddSource, e, data) {
var records=data.selections;
ddSource.grid.store.suspendEvents(false);
#{StoreLeft}.suspendEvents(false);
ddSource.grid.store.remove(records);
#{StoreLeft}.add(records);
ddSource.grid.store.resumeEvents();
#{StoreLeft}.resumeEvents();
#{ButtonOneLeft}.disable();
#{ButtonAllRight}.enable();
if(#{GridPanelRight}.store.getTotalCount()==0)
#{ButtonAllLeft}.disable();
#{GridPanelLeft}.getView().refresh();
#{GridPanelRight}.getView().refresh();
return true;
};
var notifyDropToRight = function (ddSource, e, data) {
var records=data.selections;
ddSource.grid.store.suspendEvents(false);
#{StoreRight}.suspendEvents(false);
ddSource.grid.store.remove(records);
#{StoreRight}.add(records);
ddSource.grid.store.resumeEvents();
#{StoreRight}.resumeEvents();
#{ButtonOneRight}.disable();
#{ButtonAllLeft}.enable();
if(#{GridPanelLeft}.store.getTotalCount()==0)
#{ButtonAllRight}.disable();
#{GridPanelLeft}.getView().refresh();
#{GridPanelRight}.getView().refresh();
return true;
};
</script>
</ext:XScript>
</head>
<body>
<form id="Form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" ScriptMode="Debug" SourceFormatting="True" />
<ext:Store ID="StoreLeft" runat="server">
<Reader>
<ext:JsonReader IDProperty="AddressID">
<Fields>
<ext:RecordField Name="AddressID" SortDir="ASC" />
<ext:RecordField Name="Address1" />
<ext:RecordField Name="Address2" />
<ext:RecordField Name="City" />
<ext:RecordField Name="ZIP" />
<ext:RecordField Name="Province" />
<ext:RecordField Name="Country" />
</Fields>
</ext:JsonReader>
</Reader>
<Listeners>
<Remove Handler="#{ButtonAllLeft}.enable();
#{ButtonOneRight}.disable();
#{ButtonOneLeft}.disable();
if(this.getTotalCount()==0)
#{ButtonAllRight}.disable();
else
#{ButtonAllRight}.enable();" />
</Listeners>
</ext:Store>
<ext:Store ID="StoreRight" runat="server">
<Reader>
<ext:JsonReader IDProperty="AddressID">
<Fields>
<ext:RecordField Name="AddressID" SortDir="ASC" />
<ext:RecordField Name="Address1" />
<ext:RecordField Name="Address2" />
<ext:RecordField Name="City" />
<ext:RecordField Name="ZIP" />
<ext:RecordField Name="Province" />
<ext:RecordField Name="Country" />
</Fields>
</ext:JsonReader>
</Reader>
<Listeners>
<Remove Handler="#{ButtonAllRight}.enable();
#{ButtonOneRight}.disable();
#{ButtonOneLeft}.disable();
if(this.getTotalCount()==0)
#{ButtonAllLeft}.disable();
else
#{ButtonAllLeft}.enable();" />
</Listeners>
</ext:Store>
<ext:Panel ID="Panel13" runat="server" Title="Drag/Drop (Insert Mode)" Padding="10">
<Items>
<ext:TableLayout ID="TableLayout5" runat="server" Columns="3">
<Cells>
<ext:Cell>
<ext:Panel ID="Panel14" runat="server" Layout="FitLayout" Border="true" BodyStyle="height: 260px;"
Title="Available Items">
<Items>
<ext:GridPanel ID="GridPanelLeft" runat="server" EnableDragDrop="true" DDGroup="GridPanelRightDDGroup"
Width="560" Height="250" StoreID="StoreLeft" Frame="false" Border="true" StripeRows="true"
TrackMouseOver="true" ActiveIndex="0" SelectionMemory="Enabled" Split="true"
AutoScroll="true">
<ColumnModel runat="server" ID="ColumnModel1">
<Columns>
<ext:Column ColumnID="IconColumn" MenuDisabled="true" Sortable="false" Resizable="false"
Hideable="false" Width="26">
<Renderer Fn="recordIconRenderer" />
</ext:Column>
<ext:Column ColumnID="AddressID" Header="AddressID" DataIndex="AddressID"
Hidden="true" />
<ext:Column ColumnID="Address1" Header="Address Line1" DataIndex="Address1"
Width="140" />
<ext:Column ColumnID="Address2" Header="Address Line2" DataIndex="Address2"
Width="130" />
<ext:Column ColumnID="City" Header="City" DataIndex="City" Width="80" />
<ext:Column ColumnID="ZIP" Header="Postal Code" DataIndex="ZIP" Width="80">
</ext:Column>
<ext:Column ColumnID="Province" Header="Province" DataIndex="Province"
Width="80" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel runat="server" SingleSelect="false" ID="RowSelectionModel1">
</ext:RowSelectionModel>
</SelectionModel>
<LoadMask ShowMask="true" />
<Listeners>
<RowClick Handler="#{ButtonOneRight}.enable();" />
<RowDblClick Handler="fromLeftToRight();" />
</Listeners>
</ext:GridPanel>
</Items>
</ext:Panel>
</ext:Cell>
<ext:Cell>
<ext:Panel ID="Panel1" runat="server" Border="false" Layout="VBoxLayout" BodyStyle="height: 300px;">
<Defaults>
<ext:Parameter Name="margins" Value="5 0 5 0" Mode="Value" />
</Defaults>
<LayoutConfig>
<ext:VBoxLayoutConfig Padding="5" Align="Center" Pack="Center" />
</LayoutConfig>
<Items>
<ext:Button ID="ButtonOneRight" runat="server" Icon="ResultsetNext" Width="30">
<Listeners>
<Click Handler="fromLeftToRight();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip4" runat="server" Title="Add" Html="<nobr>Add Selected Items</nobr>" />
</ToolTips>
</ext:Button>
<ext:Button ID="ButtonAllRight" runat="server" Icon="ResultsetLast" Width="30">
<Listeners>
<Click Handler="allFromLeftToRight();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip3" runat="server" Title="Add all" Html="<nobr>Add All Items</nobr>" />
</ToolTips>
</ext:Button>
<ext:Button ID="ButtonOneLeft" runat="server" Icon="ResultsetPrevious" Width="30">
<Listeners>
<Click Handler="fromRightToLeft();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip2" runat="server" Title="Remove" Html="<nobr>Remove Selected Items</nobr>" />
</ToolTips>
</ext:Button>
<ext:Button ID="ButtonAllLeft" runat="server" Icon="ResultsetFirst" Width="30">
<Listeners>
<Click Handler="allFromRightToLeft();" />
</Listeners>
<ToolTips>
<ext:ToolTip ID="ToolTip1" runat="server" Title="Remove all" Html="<nobr>Remove All Items</nobr>" />
</ToolTips>
</ext:Button>
</Items>
</ext:Panel>
</ext:Cell>
<ext:Cell>
<ext:Panel ID="Panel15" runat="server" Layout="FitLayout" Border="true" BodyStyle="height: 260px;"
Title="Selected Items">
<Items>
<ext:GridPanel ID="GridPanelRight" runat="server" EnableDragDrop="true" DDGroup="GridPanelLeftDDGroup"
Width="560" Height="250" StoreID="StoreRight" Frame="false" Border="true" StripeRows="true"
TrackMouseOver="true" ActiveIndex="0" SelectionMemory="Enabled" Split="true"
AutoScroll="true">
<ColumnModel runat="server" ID="ColumnModel2">
<Columns>
<ext:Column ColumnID="IconColumn" MenuDisabled="true" Sortable="false" Resizable="false"
Hideable="false" Width="26">
<Renderer Fn="recordIconRenderer" />
</ext:Column>
<ext:Column ColumnID="AddressID" Header="AddressID" DataIndex="AddressID"
Hidden="true" />
<ext:Column ColumnID="Address1" Header="Address Line1" DataIndex="Address1"
Width="140" />
<ext:Column ColumnID="Address2" Header="Address Line2" DataIndex="Address2"
Width="130" />
<ext:Column ColumnID="City" Header="City" DataIndex="City" Width="80" />
<ext:Column ColumnID="ZIP" Header="Postal Code" DataIndex="ZIP" Width="80">
</ext:Column>
<ext:Column ColumnID="Province" Header="Province" DataIndex="Province"
Width="80" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel runat="server" SingleSelect="false" ID="RowSelectionModel2">
</ext:RowSelectionModel>
</SelectionModel>
<LoadMask ShowMask="true" />
<Listeners>
<RowClick Handler="#{ButtonOneLeft}.enable();" />
<RowDblClick Handler="fromRightToLeft();" />
</Listeners>
</ext:GridPanel>
</Items>
</ext:Panel>
</ext:Cell>
</Cells>
</ext:TableLayout>
</Items>
</ext:Panel>
<ext:DropTarget ID="DropTarget1" runat="server" Target="={GridPanelLeft.view.scroller.dom}"
Group="GridPanelLeftDDGroup">
<NotifyDrop Fn="notifyDropToLeft" />
</ext:DropTarget>
<ext:DropTarget ID="DropTarget2" runat="server" Target="={GridPanelRight.view.scroller.dom}"
Group="GridPanelRightDDGroup">
<NotifyDrop Fn="notifyDropToRight" />
</ext:DropTarget>
</form>
</body>
</html>
Try it and tell how is it.