分享
 
 
 

Web Application 開 發 利 器 - WebSnap(七)

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Web Application 開 發 利 器 - WebSnap!

第 七 章 、 深 入 Adapter

這 一 章 的 目 的 在 於 完 全 了 解 Adapter 在 WebSnap 中 所 代 表 的 意 義 及 更 深 入 的 使 用 她 們 , 之 前 我 們 利 用 了 Adapter 與 AdapterField 來 處 理 簡 單 的 資 料 顯 示 , 如 計 算 機 程 式 , 接 著 利 用 了 DataSetAdapter 來 處 理 資 料 庫 。 但 我 想 這 對 你 來 說 還 是 不 足 以 了 解 整 個 Adapter 在 WebSnap 所 扮 演 的 角 色 , 因 此 這 一 節 我 們 將 針 對 幾 個 Adapter 做 深 入 的 運 用 , 看 完 這 一 節 後 , 相 信 你 對 Adapter 的 應 用 及 為 何 WebSnap 如 此 依 賴 她 會 有 相 當 的 體 會 。

7-1 、 簡 單 的 Adapter :TAdapter

TAdapter 是 最 簡 單 的 Adapter Container , 之 前 我 們 只 將 她 應 用 在 將 程 式 中 的 變 數 資 料 顯 示 於 網 頁 中 , 例 如 計 算 機 網 頁 , 但 她 的 能 力 可 不 僅 止 於 此 , 撇 開 撰 寫 你 自 己 的 TAdapter 元 件 這 個 技 術 不 談 ( 那 是 Inside WebSnap 的 課 題 ) , 我 們 可 以 利 用 TAdapter 來 封 裝 不 同 類 型 的 資 料 , 這 個 技 術 對 我 們 來 說 相 當 有 用 。 例 如 我 們 可 以 將 她 應 用 在 製 作 類 似 PCHome 的 檔 案 總 管 網 頁 上 , 接 下 來 我 們 先 製 作 一 個 小 程 式 , 這 個 程 式 利 用 TAdapter 來 封 裝 TStringsValueList , 並 使 用 TAdapterGrid 將 她 顯 示 在 網 頁 上 , 請 新 增 一 個 Page Module 到 專 案 中 , 將 Page Name 設 成 MyAdapter 及 選 擇 TAdapterPageProducer 為 PageProducer , 接 著 放 至 一 個 TAdapter 及 一 個 TStringsValueList 元 件 到 這 個 Module 中 , 接 著 我 們 還 要 設 定 TStringsValueList 內 的 資 料 及 AdapterField:

設 定 完 顯 示 的 資 料 後 , 我 們 還 要 加 入 兩 個 AdapterField 到 TStringsValueList 中 , 請 在 TStringsValueList 的 Field Editor 中 按 右 鍵 選 擇 Add All Fields:

要 將 資 料 顯 示 在 網 頁 上 , 我 們 還 得 在 TAdapter 中 新 增 幾 個 AdapterField 才 行 , 這 個 範 例 中 我 們 需 要 兩 個 AdapterField , 一 個 用 來 顯 示 站 名 , 另 一 個 則 用 來 顯 示 URL , 完 成 後 我 們 就 可 以 開 始 撰 寫 處 理 的 程 式 碼 , 由 於 我 們 的 目 的 是 要 使 用 TAdapterGrid 來 顯 示 TStringsValueList 中 的 資 料 。 因 此 我 們 得 撰 寫 TAdapter.OnIterateRecords 這 個 事 件 , 並 且 在 裡 面 移 動 TStringsValueList 的 記 錄 指 標 :

procedure TMyAdapter.Adapter1IterateRecords(Sender: TObject;

Action: TIteratorMethod; var EOF: Boolean);

var

Intf:IIteratorSupport;

P:Pointer;

begin

Intf:=svSite as IIteratorSupport;

case Action of

itStart:

Intf.StartIterator(P);

itNext :

EOF:=not Intf.NextIteration(P);

itEnd :

begin

Intf.EndIterator(P);

EOF:=True;

end;

end;

end;

在 這 個 事 件 中 我 們 使 用 了 一 個 介 面 :IIteratorSupport , 實 作 這 個 介 面 代 表 著 該 元 件 支 援 游 標 型 態 的 操 作 。 接 著 我 們 要 撰 寫 AdapterField 中 的 OnGetValue , 提 供 TStringsValueList 中 的 字 串 給 TAdapterGrid 使 用 :

procedure TMyAdapter.AdaptSiteNameGetValue(Sender: TObject;

var Value: Variant);

begin

Value:=AdaptNameField.Value;

end;

procedure TMyAdapter.AdaptSiteAddressGetValue(Sender:TObject;

var Value: Variant);

begin

Value:=AdaptValueField.Value;

end;

接 著 我 們 開 始 設 計 網 頁 , 開 啟 Visual Page Designer 視 窗 , 新 增 一 個 AdapterForm 及 一 個 AdapterGrid 後 , 你 會 看 到 這 樣 的 畫 面 :

然 後 執 行 程 式 後 我 們 就 可 以 看 到 成 果 了 :

很 簡 單 不 是 嗎 ? 這 個 範 例 讓 我 們 了 解 到 Adapter 的 存 在 意 義 。 我 們 可 以 使 用 TAdapter 來 封 裝 任 何 型 態 的 資 料 , 並 在 網 頁 中 顯 示 資 料 , 而 你 只 要 撰 寫 幾 個 事 件 就 可 以 了 , 這 可 以 應 用 在 許 多 地 方 , 例 如 檔 案 列 表 、 搜 尋 結 果 或 是 顯 示 一 些 非 正 規 的 資 料 庫 等 等 。 從 這 個 範 例 中 我 們 也 可 以 大 略 猜 到 TDataSetAdapter 如 何 將 資 料 庫 資 料 封 裝 起 來 , 並 提 供 她 們 給 TAdapterGrid 及 TAdapterFieldGroup 來 顯 示 。 當 然 ! 如 果 你 的 目 的 只 是 要 顯 示 TStringsValueList 中 的 資 料 的 話 , 那 直 接 將 TStringsValueList 設 給 AdapterGrid 就 行 了 , 這 裡 我 是 為 了 展 示 以 TAdapter 封 裝 某 種 資 料 的 技 術 才 這 樣 使 用 。

7-2 、 TPagedAdapter

TPagedAdapter 的 功 能 與 使 用 方 式 大 致 與 TAdapter 相 同 , 不 過 她 增 加 了 分 頁 的 能 力 , 所 謂 分 頁 的 能 力 指 的 是 當 一 個 網 頁 中 的 資 料 過 多 時 , 我 們 利 用 一 個 以 上 的 網 頁 來 顯 示 她 們 , 例 如 你 在 搜 尋 引 擎 查 出 結 果 後 , 當 結 果 筆 數 超 過 20-30 筆 時 , 你 會 看 到 網 頁 下 方 有 頁 次 顯 示 , 利 用 TPagedAdapter 我 們 可 以 輕 易 的 做 出 這 種 網 頁 。 接 下 來 就 讓 我 們 利 用 一 個 檔 案 列 表 的 範 例 程 式 來 展 示 如 何 應 用 TPagedAdpater , 請 你 新 增 一 個 Page Module 到 專 案 中 , 將 PageName 設 成 MyPageAdapter 並 選 擇 AdapterPageProducer 為 PageProducer , 接 著 放 入 一 個 TPagedAdapter 元 件 , 新 增 兩 個 AdapterField 元 件 到 裡 面 :

然 後 我 們 要 撰 寫 建 立 TStrings 物 件 , 以 及 將 檔 案 列 表 儲 存 到 TStrings 的 函 式 :

procedure TMyPageAdapter.InitializeList(AListDir:string);

var

sr: TSearchRec;

begin

FStrings.Clear;

TStringList(FStrings).Sorted:=False;

if FindFirst(AListDir,faAnyFile,sr) = 0 then

begin

repeat

if sr.Attr <> faDirectory then

FStrings.Add(sr.Name+'='+IntToStr(sr.Size));

until FindNext(sr) <> 0;

end;

TStringList(FStrings).Sorted:=True;

end;

procedure TMyPageAdapter.WebPageModuleCreate(Sender: TObject);

begin

FStrings:=TStringList.Create;

end;

procedure TMyPageAdapter.WebPageModuleDestroy(Sender: TObject);

begin

FStrings.Free;

end;

procedure TMyPageAdapter.WebPageModuleActivate(Sender: TObject);

begin

InitializeList(AppPath+'\*.*');

end;

撰 寫 TPagedAdapter 及 AdapterField 的 相 關 事 件 :

procedure TMyPageAdapter.PagedAdapter1GetEOF(Sender: TObject;

var EOF: Boolean);

begin

EOF:=not (FIndex < FStrings.Count);

end;

procedure TMyPageAdapter.PagedAdapter1GetFirstRecord(Sender: TObject;

var EOF: Boolean);

begin

FIndex:=0;

EOF:=FStrings.Count = 0;

end;

procedure TMyPageAdapter.PagedAdapter1GetNextRecord(Sender: TObject;

var EOF: Boolean);

begin

Inc(FIndex);

EOF:=not (FIndex < FStrings.Count);

end;

procedure TMyPageAdapter.PagedAdapter1GetRecordCount(Sender: TObject;

var Count: Integer);

begin

Count:=FStrings.Count;

end;

procedure TMyPageAdapter.PagedAdapter1GetRecordIndex(Sender: TObject;

var Index: Integer);

begin

Index:=FIndex;

end;

procedure TMyPageAdapter.AdaptFileNameGetValue(Sender: TObject;

var Value: Variant);

begin

Value:=FStrings.Names[FIndex];

end;

procedure TMyPageAdapter.AdaptSizeGetValue(Sender: TObject;

var Value: Variant);

begin

Value:=FStrings.Values[FStrings.Names[FIndex]];

end;

接 著 我 們 還 要 設 定 每 一 頁 中 所 顯 示 的 資 料 筆 數 :

最 後 開 啟 Visual Page Designer 加 入 AdapterForm 、 AdapterGrid 、 AdapterCommandGroup 並 設 定 Adapter 特 性 值 及 AdapterAction 後 , 你 就 可 以 看 到 如 下 的 畫 面 :

在 我 的 電 腦 上 這 個 程 式 執 行 結 果 如 下 :

你 可 以 使 用 畫 面 下 方 的 Page Link 來 切 換 頁 次 , 或 是 利 用 Prev 、 Next 來 做 上 下 頁 的 切 換 , 接 著 讓 我 們 加 強 這 個 網 頁 成 為 一 個 具 有 完 整 功 能 的 檔 案 總 管 , 要 讓 網 頁 具 有 UploadFile 的 能 力 的 話 , 我 們 必 須 新 增 一 個 新 的 TAdapter , 並 在 裡 面 新 增 一 個 TAdapterFileField:

接 著 還 要 新 增 一 個 AdapterAction , 用 來 執 行 Upload File 的 動 作 :

然 後 我 們 得 撰 寫 AdapterFileField 的 OnFileUpload 事 件 , 儲 存 使 用 者 所 上 傳 的 檔 案 :

procedure TMyPageAdapter.AdaptUploadUploadFiles(Sender: TObject;

Files: TUpdateFileList);

var

I:Integer;

fs:TFileStream;

begin

for I:=0 to Files.Count-1 do

begin

fs:=TFileStream.Create(AppPath+'\'+ExtractFileName(Files.Files[I].FileName),fmCreate);

fs.CopyFrom(Files.Files[I].Stream,Files.Files[I].Stream.Size);

fs.Free;

end;

end;

要 觸 發 這 個 事 件 , 我 們 必 須 在 AdapterAction.OnExecute 事 件 中 加 入 下 面 的 程 式 碼 :

procedure TMyPageAdapter.AdaptUploadFileExecute(Sender: TObject;

Params: TStrings);

begin

Adapter1.UpdateRecords(WebContext.AdapterRequest as IActionRequest);

end;

這 一 段 程 式 碼 的 意 思 是 更 新 TAdapter 中 的 所 有 AdapterField 資 料 , 在 這 個 程 式 中 就 是 觸 發 OnUploadFile 這 個 事 件 。 最 後 我 們 只 需 要 在 Visual Page Designer 加 入 相 關 的 元 件 就 可 以 了 :

執 行 程 式 後 你 就 可 以 上 傳 檔 案 到 這 個 網 站 上 了 , 範 例 程 式 預 設 是 C:\Temp , 你 可 以 整 合 使 用 者 管 理 功 能 來 設 定 上 傳 的 位 置 。 不 過 這 個 程 式 有 個 缺 點 , 你 會 發 現 上 傳 檔 案 後 在 網 頁 的 檔 案 列 表 中 找 不 到 你 上 傳 的 檔 案 名 稱 , 這 發 生 在 你 上 傳 的 檔 案 名 稱 經 過 排 序 後 顯 示 的 位 置 是 在 你 目 前 的 頁 次 中 , 會 這 樣 的 原 因 是 我 們 將 取 得 檔 案 列 表 的 程 式 寫 在 Module.OnActivate 之 中 , 這 跟 AdapterAction 執 行 的 順 序 有 關 , 請 看 下 面 的 流 程 :

( 圖 :8)

從 流 程 中 我 們 可 以 發 現 , OnActivate 是 在 OnExecute 之 前 觸 發 , 這 會 發 生 在 我 們 執 行 Action 之 後 所 導 向 的 網 頁 與 Action 所 在 網 頁 相 同 的 情 況 下 , 因 此 我 們 必 須 改 變 取 得 File List 程 式 碼 的 位 置 , 理 想 的 位 置 是 在 Module 的 BeforeDispatchPage 事 件 中 :

procedure TMyPageAdapter.WebPageModuleBeforeDispatchPage(Sender: TObject;

const PageName: String; var Handled: Boolean);

begin

InitializeList(AppPath+'\*.*');

end;

編 譯 後 執 行 你 就 可 以 看 到 正 常 的 結 果 了 , 接 下 來 我 們 要 加 入 刪 除 檔 案 的 能 力 , 我 們 有 兩 種 選 擇 , 一 是 像 PCHome 的 檔 案 總 管 一 樣 , 顯 示 一 個 checkbox 讓 使 用 者 選 擇 要 刪 除 的 檔 案 後 再 按 下 Delete File 按 紐 刪 除 被 選 擇 的 所 有 檔 案 。 另 一 種 是 在 Grid 最 後 一 列 顯 示 一 個 按 紐 讓 使 用 者 按 下 後 刪 除 該 列 的 那 一 個 檔 案 , 第 一 種 方 法 必 須 利 用 Session 來 儲 存 使 用 者 所 選 擇 的 檔 案 , 接 著 必 須 撰 寫 相 關 的 元 件 , 由 於 這 牽 扯 到 元 件 設 計 的 部 份 , 因 此 我 選 擇 等 到 Inside WebSnap 一 文 中 再 討 論 這 方 面 的 技 術 , 這 裡 我 們 就 先 選 擇 第 二 種 方 式 , 請 在 TPagedAdapter 中 新 增 一 個 TAdapterAction: AdaptDeleteFile 。

我 們 要 為 她 撰 寫 兩 個 事 件 :OnGetParams 與 OnExecute:

procedure TMyPageAdapter.AdaptDeleteFileExecute(Sender: TObject;

Params: TStrings);

var

FileName:string;

begin

FileName:=Params.Values['FileName'];

DeleteFile(AppPath+'\'+FileName);

end;

procedure TMyPageAdapter.AdaptDeleteFileGetParams(Sender: TObject;

Params: TStrings);

begin

Params.Add('FileName='+AdaptFileName.Value);

end;

OnGetParams 會 在 網 頁 顯 示 前 被 觸 發 , 因 此 我 們 利 用 她 的 Params 參 數 來 加 入 檔 案 名 稱 , 這 樣 當 Action 被 觸 發 時 這 個 參 數 就 會 傳 到 我 們 的 OnExecute 事 件 中 , 我 們 就 可 以 利 用 這 個 參 數 值 來 刪 除 該 檔 案 , 要 完 全 了 解 這 部 份 的 動 作 我 們 要 觀 察 網 頁 中 的 程 式 碼 :

<input type="submit" value="DeleteFile" onclick="AdapterForm1.

__act.value='FileName.13.inventory.rtf__p.13.MyPageAdapter__id.38.MyPageAdapter.PagedAdapter1.DeleteFile'">

你 可 以 看 到 紅 色 字 的 部 份 , 這 就 是 我 們 在 OnGetParams 所 填 入 的 參 數 值 , 當 使 用 者 按 下 按 紐 後 TAdapterDispatcher 會 取 出 這 個 參 數 值 並 送 到 我 們 的 OnExecute 事 件 中 。 完 成 設 計 網 頁 的 動 作 後 這 個 程 式 就 算 完 成 了 , 你 已 經 擁 有 一 個 簡 單 的 檔 案 總 管 了 , 接 下 來 你 可 以 結 合 使 用 者 管 理 與 其 它 一 些 控 制 之 後 , 就 可 以 達 到 類 似 PCHome 個 人 網 頁 的 能 力 了 , 這 些 就 當 成 是 你 的 練 習 題 了 。

7-3 TOrpEditablePagedAdapter

原 本 我 一 直 避 免 在 這 篇 文 章 中 論 及 元 件 設 計 , 可 是 我 後 來 想 想 , 這 個 範 例 對 你 來 說 可 能 是 蠻 有 用 的 , 但 是 我 不 打 算 在 這 篇 文 章 中 解 釋 元 件 設 計 , 因 為 那 得 用 一 篇 文 章 才 能 交 代 各 個 Interface 間 的 互 動 及 協 調 , 但 我 又 很 想 將 這 個 範 例 與 你 分 享 , 所 以 我 下 了 個 決 定 , 我 將 元 件 給 你 , 但 原 始 碼 等 到 Inside WebSnap 時 再 詳 細 的 解 釋 ! 還 記 得 我 們 上 一 節 的 範 例 嗎 ? 基 本 上 看 起 來 是 很 不 錯 , 但 是 我 們 必 須 承 認 , 她 還 不 是 很 實 用 , 也 不 足以 啟 發 你 其 它 的 聯 想 , 所 以 我 完 成 了 這 個 範 例 , 要 編 譯 這 個 範 例 , 你 必 須 要 先 安 裝 Orpdemo.bpl 這 個 Package , 裡 面 有 一 個 TOrpEditablePagedAdapter 元 件 , 她 是 基 於 TPagedAdapter 再 加 入 可 編 修 資 料 的 能 力 , 我 們 利 用 她 來 完 成 我 們 上 一 節 中 未 完 成 的 範 例 , 這 個 檔 案 總 管 可 以 讓 使 用 者 先 挑 選 要 刪 除 的 資 料 , 之 後 按 下 刪 除 的 按 紐 後 刪 除 資 料 , 這 不 只 可 以 用 在 刪 除 檔 案 , 你 也 可 以 利 用 她 來 將 使 用 者 選 擇 的 檔 案 壓 縮 後 讓 使 用 者 下 載 , 亦 或 是 購 物 車 , 或 者 更 多 地 方 ! 這 也 是 我 為 何 會 破 例 在 這 篇 文 章 中 展 示 她 的 原 因 , 含 意 太 深 了 , 讓 我 不 能 忽 視 ! 完 整 的 範 例 程 示 在 uMySessionPagedAdapter Unit 中 , 我 只 挑 出 幾 個 部 份 來 解 釋 , 請 你 對 照 著 看 , 首 先 我 們 使 用 TOrpEditablePagedAdapter 來 取 代 TPagedAdapter 列 示 檔 案 的 程 式 碼 與 上 節 的 範 例 相 同 , 我 們 先 解 釋 處 理 Session 的 部 份 :

function TMySessionPagedAdapter.AddToList(Value:string):Boolean;

begin

Result:=True;

if not FindSession(Value,foNothing) then

begin

if not FindSession('',foNothing,Value) then

begin

try

VarArrayUnLock(FSessionVariant);

VarArrayRedim(FSessionVariant,FDeleteArraySize+1);

FDeleteArray:=VarArrayLock(FSessionVariant);

FDeleteArray[FDeleteArraySize+1]:=Value;

Inc(FDeleteArraySize);

except

Result:=False;

end;

end;

end;

end;

function TMySessionPagedAdapter.FindSession(Value:string;FindOperation:TFindOperation;AddValue:string=''):Boolean;

var

I:Integer;

bFind:Boolean;

begin

bFind:=False;

if FDeleteArraySize <> -1 then

begin

for I:=0 to FDeleteArraySize do

begin

if (not VarIsEmpty(FDeleteArray[I])) and (Value = FDeleteArray[I]) then

begin

bFind:=True;

if FindOperation = foDelete then

FDeleteArray[I]:=Unassigned;

break;

end;

if (Value = '') and (AddValue <> '') and (VarIsEmpty(FDeleteArray[I])) then

begin

bFind:=True;

FDeleteArray[I]:=AddValue;

break;

end;

end;

end;

Result:=bFind;

end;

AddToList 及 FindSession 是 用 來 處 理 Session 的 程 式 , 我 們 利 用 了 一 個 Variant Array 來 儲 存 使 用 者 所 挑 選 的 檔 案 名 稱 , FDeleteArray 是 一 個 陣 列 指 標 , 我 們 在 操 作 Variant Array 之 前 會 先 使 用 VarArrayLock 來 加 快 處 理 Variant Array 的 速 度 .

procedure TMySessionPagedAdapter.WebPageModuleBeforeDispatchPage(

Sender: TObject; const PageName: String; var Handled: Boolean);

begin

InitializeList(AppPath+'\*.*');

FSessionVariant:=Session.Values['DeleteList'];

if VarIsEmpty(FSessionVariant) then

begin

FSessionVariant:=VarArrayCreate([0,0],varVariant);

FSessionVariant[0]:=Unassigned;

Session.Values['DeleteList']:=FSessionVariant;

FDeleteArraySize:=0;

end

else

FDeleteArraySize:=VarArrayHighBound(FSessionVariant,1);

FDeleteArray:=VarArrayLock(FSessionVariant);

end;

我 們 選 擇 了 在 BeforeDispatchPage 事 件 中 將 Session 取 出 並 Lock 後 對 應 至 FDeleteArray 中 。

procedure TMySessionPagedAdapter.WebPageModuleAfterDispatchPage(

Sender: TObject; const PageName: String);

begin

VarArrayUnLock(FSessionVariant);

Session.Values['DeleteList']:=FSessionVariant;

end;

在 Dispatch 之 後 我 們 將 Variant UnLock 後 存 回 Session 中 。

procedure TMySessionPagedAdapter.AdaptDeleteGetValue(Sender: TObject;

var Value: Boolean);

begin

Value:=FindSession(AdaptFileName.Value,foNothing);

end;

我 們 在 這 個 範 例 中 提 供 一 個 checkbox 在 每 一 筆 資 料 後 面 , 這 個 值 必 須 由 Session 中 取 出 。

procedure TMySessionPagedAdapter.AdaptDeleteUpdateValue(Sender: TObject;

Value: Boolean);

begin

AddToList(FStrings.Names[OrpEditablePagedAdapter1.CurrentUpdateIndex])

end;

當 使 用 者 選 定 檔 案 或 是 切 換 至 其 它 的 Page 時 , 我 們 要 執 行 Adapter 的 UpdateRecords 函 式 , 她 會 觸 發 AdapterField 的 UpdateValue 事 件 , 這 裡 我 們 使 用 了 TOrpEditablePagedAdapter 的 特 有 屬 性 :CurrentUpdateIndex , 這 個 屬 性 會 告 知 我 們 目 前 更 新 的 記 錄 位 置 , 我 們 再 由 FStrings 取 出 對 應 的 檔 名 .

procedure TMySessionPagedAdapter.ActionPrevPageBeforeExecute(

Sender: TObject; Params: TStrings; var Handled: Boolean);

var

I,iClearStart,iClearEnd:Integer;

begin

FSessionVariant:=Session.Values['DeleteList'];

FDeleteArray:=VarArrayLock(FSessionVariant);

iClearStart:=OrpEditablePagedAdapter1.RecordIndex;

iClearEnd:=OrpEditablePagedAdapter1.PageSize +

OrpEditablePagedAdapter1.RecordIndex;

if iClearEnd > (FStrings.Count-1) then

iClearEnd:=FStrings.Count-1;

for I:=iClearStart to iClearEnd do

FindSession(FStrings.Names[I],foDelete);

OrpEditablePagedAdapter1.UpdateRecords((WebContext.AdapterRequest as IActionRequest));

VarArrayUnlock(FSessionVariant);

Session.Values['DeleteList']:=FSessionVariant;

end;

你 可 以 在 範 例 程 式 中 發 現 我 將 Goto , Prev , NextPage 三 個 Action 的 BeforeExecute 事 件 都 指 向 了 這 個 事 件 , 這 是 為 了 讓 使 用 者 操 作 方 便 , 不 需 要 再 按 另 一 個 按 紐 來 更 新 所 選 擇 的 檔 案 。

procedure TMySessionPagedAdapter.AdaptDeleteFileExecute(Sender: TObject;

Params: TStrings);

var

I:Integer;

begin

FSessionVariant:=Session.Values['DeleteList'];

FDeleteArray:=VarArrayLock(FSessionVariant);

OrpEditablePagedAdapter1.UpdateRecords((WebContext.AdapterRequest as IActionRequest));

for I:=0 to FDeleteArraySize do

begin

if (not VarIsEmpty(FDeleteArray[I])) and

(FDeleteArray[I] <> '') then

begin

DeleteFile(AppPath+'\'+FDeleteArray[I]);

FDeleteArray[I]:=Unassigned;

end;

end;

FSessionVariant:=VarArrayCreate([0,0],varVariant);

Session.Values['DeleteList']:=FSessionVariant;

end;

前 三 行 程 式 是 更 新 Session 資 料 用 , 後 面 的 程 式 則 是 執 行 刪 除 檔 案 的 動 作 . 其 實 這 個 範 例 不 算 很 複 雜 , 只 是 她 裡 面 展 示 了 Session 的 應 用 , 這 對 我 們 在 撰 寫 其 它 程 式 時 相 當 有 用 , 另 外 你 可 以 發 現 到 我 在 PrevPageBeforeExecute 中 所 寫 的 程 式 碼 會 在 執 行 Action 前 清 空 該 頁 中 的 選 項 , 要 了 解 我 為 何 這 樣 寫 的 原 由 , 你 必 須 要 使 用 WebAppDebuger 中 的 Log 來 觀 察 當 你 選 擇 了 某 個 檔 案 後 Post 的 資 料 , 以 及 當 你 移 除 了 一 個 選 擇 時 的 Post 資 料 , 兩 相 對 照 後 就 會 有 答 案 了 . (PS: 永 遠 不 會 送 出 False 的 checkbox)

本 章 後 記

這 一 節 中 我 們 了 解 了 Adapter 在 WebSnap 中 的 定 位 及 各 種 應 用 , 也 討 論 了 Action 一 些 事 件 的 意 義 , 並 結 合 這 些 技 術 建 構 了 一 個 簡 單 的 檔 案 總 管 , 到 本 節 為 止 , 我 們 也 介 紹 了 近 8 成 以 上 的 WebSnap 元 件 。

PS: 小 心 誤 刪 掉 了 某 些 檔 案 !!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有