看過之前設計器截圖的朋友應該有印象,可能會發覺我們的設計器UI設計布局其實類似Visual studio 的設計界面,采用的是左、中、右三個區域布局。左側為控件區域、中間為表單的畫布設區域、右側為屬性區域。這樣的UI設計肯定就得支持控件的拖拽設計,用戶只要拖放一個控件到我們的畫布上,那么畫布就應該立即能夠看到我們拖放的控件在畫布中的位置、大小、以及一些控件自帶的默認信息。不用說這樣的設計對於用戶來說不論在操作體驗上還是設計的感官上都更加直接和方便,因為我在設計階段就可以知道我設計后的表單在系統運行時候的樣子(What i see is what i get)。這個設計相對於我們1.0版本的設計器來說應該是很大的進步,要知道在1.0時代我們的設計器可是一個通過彈出框,然后在彈出框的下拉控件列表去選擇控件類型,然后配置其他的xx屬性......然后所有控件顯示到一個grid列表中的,用戶更不不知道這個表單是什么樣子,還需要借助預覽功能才能查看表單的樣子。
我們的設計器既然要采用類似VS設計器的方式,那么我們也就必須解決一些比較重要的問題。
- 首先來說就是必須要支持控件的拖拽設計,也就是當用戶進入我們的設計器界面,選擇了左側的某個控件后能夠拖放到我們設計器的中間畫布“指定”區域(注意是指定的位置,不是順便一個位置)。
- 然后就是不同區域支持的控件類型可能不一樣,那么我們就必須限定每個類型的區域控件能夠支持哪些控件。也就是當一個被區域支持的控件拖放到我們的區域上面並釋放鼠標后那么我們的區域就得接受該控件,如果是不被支持的控件拖放到我們的區域上面並釋放鼠標后我們的區域控件不會有任何響應。
- 同一個區域內部的控件支持隨意的交換位置,用戶可在一個區域內部通過拖放控件來改變控件的位置。
- 我們的區域之間能夠支持控件的拖放,比如將一個A區域的控件移動到B區域中區。也就是區域之間可以隨意交換控件。
上面的幾個問題是我們采用拖拽式表單設計器必須解決的問題,如何解決呢?通過研究extjs API 我們可以發現,對於extjs treepanel類型控件我們在它的view里面添加一個支持樹節點拖放的treeviewdragdrop插件,實現代碼如下:(請對比Ext.net 的寫法和 純extjs的寫法上的區別.其實它們本質上是一樣的,Ext.Net的代碼在經過服務器解析之后生成的代碼其實和純extjs寫的代碼幾乎一樣。只是Ext.Net對.Net開發人員來說使用起來更方便,更熟悉,僅此而已.)

1 <ext:TreePanel ID="controlRegion" Title="表單控件" runat="server" Region="West" RootVisible="false" 2 Width="200" Split="true" Collapsible="true" Collapsed="false"> 3 <Store> 4 ...........................略 5 </Store> 6 <Root> 7 ...........................略 8 </Root> 9 <View> 10 <ext:TreeView ID="TreeView1" runat="server"> 11 <Plugins> 12 <ext:TreeViewDragDrop runat="server" EnableDrop="true" DragGroup="tree2div" /> 13 </Plugins> 14 </ext:TreeView> 15 </View> 16 </ext:TreePanel>

Ext.create("Ext.tree.Panel",
{
store: { //.........略 },
id: "TreePanel1",
width: 200,
region: "west",
split: true,
collapsible: true,
title: "表單控件",
viewConfig: {
id: "TreeView2",
plugins: [
{
ptype: "treeviewdragdrop",
dragGroup: "tree2div"
}
],
xtype: "treeview"
},
root: { //.........略 },
rootVisible: false
})
請注意代碼中的包含treeviewdragdrop部分的代碼,它的加入表示我們的樹節點可以支持拖放了,但是僅僅這樣還是遠遠不夠的。我們還必須為我們設計器的畫布提供接收拖放功能的代碼,這里我們給出畫布區域的代碼和對畫布支持拖放的代碼。
我們的設計器代碼中加入一個畫布的panel ,結合前面一章節的介紹大家應該知道我們的畫布其實是一個Mixed類型的混合區域控件。
1 <ext:Panel ID="mainPanel" runat="server" Region="Center" ButtonAlign="Center" Border="true" 2 BodyPadding="10" OverflowY="Auto"> 3 <CustomConfig> 4 <ext:ConfigItem Name="type" Value="Mixed" Mode="Value" /> 5 </CustomConfig> 6 </ext:Panel>
然后我們使用一個Droptarget來為我們的畫布添加可以接收拖動釋放的控件的功能
<ext:DropTarget ID="ddt" runat="server" Target="mainPanel" Group="tree2div" IgnoreSelf="false"> <NotifyDrop Fn="notifyDrop" /> <NotifyEnter Handler="ftConfig.isDraging=true;" /> </ext:DropTarget>
在這里注意一個地方就是在droptarget里面的group屬性值為tree2div,這個值和我們前面給treepanel添加的treeviewdragdrop 的DragGroup屬性值是必須一致的,不然是不能正常工作的。到目前為止我們其實僅僅解決了樹的節點可以拖放,以及我們的mainpanel畫布支持接受拖放過來的控件。但是我們的畫布如何處理拖放過來的控件,以及每種區域控件可以接收的控件等等功能還得我們去設計和定義,具體的設計以及實現留到下一節吧。