演示+代码
一 目标及要求:
设计一个小程序,用以记录备忘等小东西,需要有一个目录,一个按照目录分门别类的显示目录下的Notes.同时应具有,CRUD[Create,Read,Update,Delete]目录与Note的功能,Tree的dataprovider不能为XML,应使用ITreeDataDescriptor.所有数据存放于SharedObject中.
二 设计:
1.XML大概格式:
<cat label="SimpleNoteManagement">
<cat label="Cat1">
<note title="Notetitle0" date="Tue Aug 12 2008 12:00:00 AM" detail="Note0detail"/>
<cat labe="Cat1.1>
<note title="Notetitle1" date="Tue Aug 12 2008 12:00:00 AM" detail="Note1detail"/>
<note title="Notetitle2" date="Tue Aug 12 2008 12:00:00 AM" detail="Note2detail"/>
</cat>
</cat>
<cat label="Cat2"/>
</cat>
2.上述XML将存储与SharedObject中.
3.类设计:
Category:
public static var root : Category;
public var label : String;
public var subCats : ArrayCollection;
public var notes : ArrayCollection;
public var parent : Category;
public function addSubCat(item:Category):void
public function addNote(note:Note):void
public function delCat(item:Category):void
public function delNote(note:Note):void
public function catToXml():XML
public function toXML():XML
Note:
public var title :String;
public var date : String;
public var detail :String;
public var parent:Category;
public function noteToXml():XML
4.系统初始化时,读取XML,并将之转换为Category对象.通过Category中subCats与notes,分别为Tree及datagrid提供数据.
5.设计操作过程;Cat与Note的CRUD.
6.操作结束后,将Category转换为XML,存储与SharedObejct.
三 详细设计:
1.程序初始化及读取XML转换为Catefory对象:
/**
* 初始化函数.首先调用loadXML()函数以获取SharObject中的XML数据.
* 然后通过readCat将XML数据读取为对象,并将最顶级的Root对象返回给root.
* root为Category类的static变量.
*/
public function onComplete():void {
cats = loadXML();
Category.root = readCat(cats);
trace(Category.root.label);
setButton();
}
loadXML函数:
public function loadXML():XML{
var NoteManagementShareObject:SharedObject = SharedObject.getLocal("NoteManagementShareObjectSave");
trace((NoteManagementShareObject.data.catandnote as XML).toXMLString());
return NoteManagementShareObject.data.catandnote;
}
readCat函数:
/**
* 遍历XML,首先判断xml.localName是否为cat,如果是,则说明此xml为我们要求的含有目录信息的xml,可以通过下面代码进行解析,如果不是则返回错误.
* 回溯:首先,因为已经确定xml.localName是"cat",因此新建一个Category,并赋值.
* 然后判断他的孩子,在他的孩子中遍历:
* 如果localName是cat的,为目录,运行readCat,创建一个category,如果发现孩子还有孩子,并且还有cat,则继续执行,直到最最底层,然后将最后一个
* category[subcat]的parent设置为newcat,并把category[subcat]添加到newcat的subCats中,以此执行,直到完成整个回溯过程.
* 如果localName是note,则直接新建note,赋值,加入到newcat.notes中.
*/
至此,初始化完成,并取得具有牵头作用的root.
2.Tree实现:
<mx:Tree dataDescriptor="{new CategoryTreeDataDiscriptor()}" x="40" y="90" labelField="lebal"
dataProvider="{Category.root}" width="228" height="484"
showRoot="false" click="categoryClickHand();" id="treeCategory" ></mx:Tree>
CategoryTreeDataDiscriptor函数:
public class CategoryTreeDataDiscriptor implements ITreeDataDescriptor
{
/**
* 取得node的children,也就是node的subCats,故使用node as category来调用subCats
*/
public function getChildren(node:Object, model:Object=null):ICollectionView
{
return (node as Category).subCats;
}
/**
* 判断node是否有孩子.
* subCats有可能不为空,但没有内容,因此,如果为空或没有内容,则应返回false
* 注意If语句的条件.如果互换位置,则将报错,因为If将先执行or的第一部分,如果互换,遇到空则报错.
*/
public function hasChildren(node:Object, model:Object=null):Boolean
{
var hasC:Boolean = true;
if ((node as Category).subCats == null || (node as Category).subCats.length < 1) {
hasC = false
}
return hasC;
}
/**
* 判断是否为分支
* 应直接使用hasChildren返回值,便于后期的管理与修改.
*/
public function isBranch(node:Object, model:Object=null):Boolean
{
return hasChildren(node,model);
}
public function getData(node:Object, model:Object=null):Object
{
return node;
}
public function addChildAt(parent:Object, newChild:Object, index:int, model:Object=null):Boolean
{
throw Error("Not Supported");
}
public function removeChildAt(parent:Object, child:Object, index:int, model:Object=null):Boolean
{
throw Error("Not Supported");
}
}
3.datagrid实现:
步骤2中的Click函数:
/**
* 响应Tree的状态.在点击Tree的时候,设定右侧用于显示Note的datagrid的dataprovider.
*
*/
private function categoryClickHand():String {
var rowNumber:String;
if (treeCategory.selectedItem == null){
buttonDelCat.enabled = false;
buttonEditCat.enabled = false;
}
else if ((treeCategory.selectedItem as Category).notes != null){
//noteUI.datagridNotes.dataProvider=(treeCategory.selectedItem as Category).notes;
dataGridNoteList.dataProvider=(treeCategory.selectedItem as Category).notes;
rowNumber = String((treeCategory.selectedItem as Category).notes.getItemIndex((treeCategory.selectedItem as Category).notes) + 1);
trace(rowNumber);
}
return rowNumber;
}
至此,初步实现对XML的读取与实现.
4.对象转换为XML,并存储
/**
* 保存XML.
* 定义变量:NoteManagementShareObject类型为SharedObject,赋值.
* 通过toXML函数,通过root对象的subcats将所有cat对象读取出为XML.
* 并将该XML写入到SharedObject中.
*/
public function save(givenParentXML:XML = null):void{
var NoteManagementShareObject:SharedObject = SharedObject.getLocal("NoteManagementShareObjectSave");
Category.root.toXML();
trace(Category.root.toXML().toXMLString());
givenParentXML.appendChild(Category.root.toXML());
NoteManagementShareObject.data.catandnote = Category.root.toXML();
NoteManagementShareObject.flush();
}
toXML函数:
/**
* 通过回溯,将对象转换为XML
*/
public function toXML():XML {
var parentXML : XML = <cat label={label}></cat>;
var noteCounter:int;
var catCounter:int;
//添加note
//if (notes != null && notes.length>0) {
for(noteCounter = 0; notes != null && notes.length>0&¬eCounter < notes.length; noteCounter++){
parentXML.appendChild((notes[noteCounter] as Note).noteToXml());
}
//}
//如果含有分支,则将分支进行writeToXml;
//if (subCats != null && subCats.length>0) {
for(catCounter = 0; subCats != null && subCats.length>0&&catCounter < subCats.length ; catCounter++) {
parentXML.appendChild((subCats[catCounter] as Category).toXML());
}
//}
return parentXML;
}
至此,程序的读取与保存工作已完成.下面是中间操作:
5.以Note举例,列举其CRUD步骤
5.1 Create:
/**
* Note增加函数,新建一个note对象,调用Category中的addNote函数.该函数将新建的Note对象追加到相对应的cat的notes arraycollection中.
*/
public function addNewNote():void {
var noteTobeAdded:Note = new Note();
noteTobeAdded.title = inputTitle.text;
noteTobeAdded.date = inputDate.selectedDate.toLocaleString();
noteTobeAdded.detail = inputDetail.text;
noteTobeAdded.parent = treeCategory.selectedItem as Category;
(treeCategory.selectedItem as Category).addNote(noteTobeAdded);
}
public function addNote(note:Note):void{
if(notes == null) {
notes = new ArrayCollection();
}
notes.addItem(note);
}
5.2 Read:
列表将通过datagrid实现,前面通过tree的点击响应函数categoryClickHand()已经实现.每个Note的显示类似于Update部分.
5.3 Update:
/**
* Note编辑函数,新定义一个EditWindow[专门用来编辑Note的TitleWindow],定Title,定义要传递的对象,注册对编辑结束事件的监听.
* 在点击之后弹出该窗口
*/
public function editTheNote():void{
//定义一个对话框
var noteEditer:EditWindow = EditWindow(PopUpManager.createPopUp(this,EditWindow,true));
noteEditer.title="NoteUpdate";
noteEditer.note = dataGridNoteList.selectedItem as Note;
noteEditer.addEventListener(EventEditComplete.EVENTEDITCOMPLETE,onEditComplete);
PopUpManager.centerPopUp(noteEditer);
}
弹出窗口内的函数:
public function set note(n:Note):void{
_note = n;
inputTitle.text = _note.title;
inputDate.selectedDate = new Date(_note.date);
inputDetail.text = _note.detail;
trace("Update set is called");
trace(_note.title);
}
public function get note():Note{
return _note;
}
public function upDateTheNoteAndDispatch():void{
_note.title = inputTitle.text;
_note.date = String(inputDate.selectedDate);
_note.detail = inputDetail.text;
var e:EventEditComplete;
e = new EventEditComplete();
dispatchEvent(e);
PopUpManager.removePopUp(this);
}
5.4 Delete:
//Note删除函数,使用note的parent,调用delNote函数.
public function delTheNote():void {
(dataGridNoteList.selectedItem as Note).parent.delNote(dataGridNoteList.selectedItem as Note);
treeCategory.invalidateList();
}
delNote函数:
public function delNote(note:Note):void {
note.parent.notes.removeItemAt(note.parent.notes.getItemIndex(note));
}
四:测试及抓图:
测试 略
五:出现问题及解决方法:
1.读取或写入XML函数出错:应先在纸上画出执行过程,仔细分析后设计或修改函数
2.Tree的ITreeDataDescriptor不会使用:应对照API及相关帮助文档进行设计.
六:相关知识点总结
1.Tree ITreeDataDescriptor
2.SharedObject
3.Event
七:其他
设定在tree或datagrid无选定时部分按钮,如编辑,删除等无效的方法:
1. 将相关按钮enable设置为flash.
2. 在程序初始化时,call一个函数:setButton(); setButton可以相应tree或datagrid的点选,以设定按钮状态
3.setButton函数:
public function setButton():void{
dataGridNoteList.addEventListener(ListEvent.CHANGE,setNoteButtonState);
treeCategory.addEventListener(ListEvent.CHANGE,setButtonCatState);
}
4.响应函数:以Note举例;
public function setNoteButtonState(event:ListEvent):void{
if (dataGridNoteList.selectedItem != null){
buttonEditNote.enabled = true;
buttonDelNote.enabled = true;
buttonViewDetail.enabled = true;
} else {
buttonEditNote.enabled = false;
buttonDelNote.enabled = false;
buttonViewDetail.enabled = false;
}
}
组件本身enable为false,当selected的时候变为true,功能已经实现了,为什么还要加else呢?
因为选定之后,按ctrl+鼠标单击,selected的状态已经改变,但是button仍然可用,因为此时并没有任何响应该状态的函数.加入else之后,可以解决这个问题.
回應
... some code here ...
- public function loadXML():XML{
- var NoteManagementShareObject:SharedObject = SharedObject.getLocal("NoteManagementShareObjectSave");
- trace((NoteManagementShareObject.data.catandnote as XML).toXMLString());
- return NoteManagementShareObject.data.catandnote;
- }
public function loadXML():XML{ var NoteManagementShareObject:SharedObject = SharedObject.getLocal("NoteManagementShareObjectSave"); trace((NoteManagementShareObject.data.catandnote as XML).toXMLString()); return NoteManagementShareObject.data.catandnote; }
- public function loadXML():XML{
- var NoteManagementShareObject:SharedObject = SharedObject.getLocal("NoteManagementShareObjectSave");
- trace((NoteManagementShareObject.data.catandnote as XML).toXMLString());
- return NoteManagementShareObject.data.catandnote;
- }
- <PRE class=js name="code"><A onmouseover="alert('对不起,图片不能随便下载!')" href="javascript:void(0)" jQuery1221017308187="25"><IMG height=50 src="j2.gif" width=99 align=center border=0></A>
- </PRE>
- 转自:http://riashanghai.com/node/27