如何把 Available DataSet 放進 Property Editor? |
尚未結案
|
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
我已初步懂得製作 Property Editor, 例如我已知道如何把字串放入 ComboBox, 放入 Object inspector 中讓人選擇:
TKeyFieldProperty = class(TStringProperty) private public function GetAttributes: TPropertyAttributes; override; procedure GetValues(Proc: TGetStrProc); override; end; procedure Register; begin RegisterComponents('Example', [TMyClientDataSet]); RegisterPropertyEditor(TypeInfo(String), TMyClientDataSet, 'PrimaryKey', TKeyFieldProperty); end; function TKeyFieldProperty.GetAttributes: TPropertyAttributes; begin Result := inherited GetAttributes [paValueList]; end; procedure TKeyFieldProperty.GetValues(Proc: TGetStrProc); begin Proc('Field1'); Proc('Field2'); end;現在我想把候選 DataSet 放入 ComboBox 中, 而不是上例的 String, 該如何做呢? -- 小卜子
------
-- 小卜子 |
william
版主 ![]() ![]() ![]() ![]() ![]() 發表:66 回覆:2535 積分:3048 註冊:2002-07-11 發送簡訊給我 |
Perhaps it could give you some hints:
|
l630521
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
不好意思!你如果要把可選取的DataSet在Object inspector可讓人選取的話
unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TDataSet; protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TDataSet read FDataSet write FDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; end.直接設一property是TDataSet型態,Delphi就會自動把所有可用的DataSet讓你選取了不是嗎?為什麼還要特別去處理呢?請問你的目的為何啊? Ian |
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言: 不好意思!你如果要把可選取的DataSet在Object inspector可讓人選取的話啊, 是的, 的碓是自動做了給我, 那麼, 若果我想讓可選 DataSet 做些篩選, 例如只讓 TClientDataSet 才出現在這 DataSet ComboBox 中, 又如何處理呢? -- 小卜子unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TDataSet; protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TDataSet read FDataSet write FDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; end.直接設一property是TDataSet型態,Delphi就會自動把所有可用的DataSet讓你選取了不是嗎?為什麼還要特別去處理呢?請問你的目的為何啊? Ian
------
-- 小卜子 |
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言: 不好意思!你如果要把可選取的DataSet在Object inspector可讓人選取的話啊, 是的, 的確是自動做了給我, 那麼, 若果我想讓可選 DataSet 做些篩選, 例如只讓 TClientDataSet 才出現在這 DataSet ComboBox 中, 又如何處理呢? -- 小卜子unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TDataSet; protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TDataSet read FDataSet write FDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; end.直接設一property是TDataSet型態,Delphi就會自動把所有可用的DataSet讓你選取了不是嗎?為什麼還要特別去處理呢?請問你的目的為何啊? Ian
------
-- 小卜子 |
l630521
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TClientDataSet; protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TClientDataSet read FDataSet write FDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; end.把TDataSet改成TClientDataSet就可以了! Ian |
hahalin
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:295 回覆:1698 積分:823 註冊:2002-04-14 發送簡訊給我 |
type TTest = class(TComponent) private { Private declarations } FDataSet: TClientDataSet; protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TClientDataSet read FDataSet write FDataSet; end; |
hahalin
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:295 回覆:1698 積分:823 註冊:2002-04-14 發送簡訊給我 |
|
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言:不行。 說來話要長一點, 因為, 我實際要放入這個 TTest 中的 DataSet, 並非 TDataSet, 亦非 TClientDataSet, 而是小弟自己寫的 TXClientDataSet, 而這個 TTest.DataSet 屬性, 便是供給放入 TXClientDataSet 物件, 而 TTest.DataSet 屬性的類別, 我是使用 TDataSet 就算了, 之所以不直接把 DataSet 屬性設定為 TXClientDataSet, 是有點苦衷的, 因為 TTest Class 與 TXClientDataSet Class 出現了 "Cyclic unit reference" 問題, 這是一直困擾著我的難題, 就例如現在這兩個 Class, 我的 TTest 中大量的使用著 TXClientDataSet, 而 TXClientDataSet 卻只有其中一個屬性指向 TTest, 結果兩者都要在 interface 區域的 uses 中加入對方的 Class reference, 結果就出現了 "Cyclic unit reference" 問題。 我懂得的解決方法只有兩個: 1. 某一方的 Class 中使用對方的 Class 的父類別, 然後在 Implementation 中不斷使用 Type casting 來解決。例如現在, 我就是採取了這方法, 我把 TTest 中的 DataSet 不設為 TXClientDataSet, 而只設為 TClientDataSet (或 TDataSet, 沒所謂); 2. 把兩個 Class 擠進一個 unit 中, 這個方法我覺得甚劣, 因為兩個 Class 的程式碼均甚多, 並有繼續發展之勢。我嘗試過使用 #include 來把併合了的大怪物分柝, 但效果不好, 因為 #include 使用上有很多限制。 所以, 若能解決這個 Cyclic unit reference 問題, 這條題便自然迎刃而解了, 可是, 即使我到 Borland newsgroup 找解決方案, 都找不出第三個方案出來, 你有建議嗎? 否則, 便要用老方法, 想想如何讓 Property inspector 把 TXClientDataSet 篩選出來, 放入 TDataSet (或 TClientDataSet) 類別的屬性之中了。 -- 小卜子unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TClientDataSet; protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TClientDataSet read FDataSet write FDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; end.把TDataSet改成TClientDataSet就可以了! Ian
------
-- 小卜子 |
hahalin
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:295 回覆:1698 積分:823 註冊:2002-04-14 發送簡訊給我 |
unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TDataSet; procedure setfdataset(value:tdataset); protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TDataSet read FDataSet write setFDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; procedure TTest.setFdataset(value:tdataset); begin if value <> fdataset then begin if (uppercase(fdataset.classname)='TXClIENTDATASET') then begin fdataset:=value; end; end; end; end.發表人 - hahalin 於 2004/05/17 13:30:52 |
speedup
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
TMyDataSetProperty = class(TComponentProperty) private public function GetAttributes: TPropertyAttributes; override; procedure GetValues(Proc: TGetStrProc); override; end; procedure Register; begin RegisterComponents('Example', [TXClientDataSet]); RegisterPropertyEditor(TypeInfo(TDataSet), TXClientDataSet, 'XXXProperty', TMyDataSetProperty); end; function TMyDataSetProperty.GetAttributes: TPropertyAttributes; begin Result := inherited GetAttributes [paValueList]; end; procedure TMyDataSetProperty.GetValues(Proc: TGetStrProc); begin Designer.GetComponentNames(GetTypeData(TypeInfo(TXClientDataSet)),Proc); end;混心雜欲 棄修身~唉
------
唉~ |
hahalin
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:295 回覆:1698 積分:823 註冊:2002-04-14 發送簡訊給我 |
|
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言:謝謝你的回答。 事實上, 我已經這樣做了。這個做法可以達致「用戶選了 TXClientDataSet 以外的 DataSet Class object 時, 會 Prompt error」, 而未能做到一開始便只把 TXClientDataSet objects 放在 ComboBox 內讓人選擇。 不過, 現在我也算是得到解決了, 因為我一開始時不知道, 只要是 TDataSet 的屬性, Property Inspector 便會自動將之變成 ComboBox 讓人選擇。 在此一併多謝 William, 你的方法我往後寫 Component 時必會用得上。 -- 小卜子unit Test; interface uses SysUtils, Classes, DB; type TTest = class(TComponent) private { Private declarations } FDataSet: TDataSet; procedure setfdataset(value:tdataset); protected { Protected declarations } public { Public declarations } published { Published declarations } property DateSet: TDataSet read FDataSet write setFDataSet; end; procedure Register; implementation procedure Register; begin RegisterComponents('Test', [TTest]); end; procedure TTest.setFdataset(value:tdataset); begin if value <> fdataset then begin if (uppercase(fdataset.classname)='TXClIENTDATASET') then begin fdataset:=value; end; end; end; end.發表人 - hahalin 於 2004/05/17 13:30:52
------
-- 小卜子 |
speedup
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
引言: 我懂得的解決方法只有兩個: 1. 某一方的 Class 中使用對方的 Class 的父類別, 然後在 Implementation 中不斷使用 Type casting 來解決。例如現在, 我就是採取了這方法, 我把 TTest 中的 DataSet 不設為 TXClientDataSet, 而只設為 TClientDataSet (或 TDataSet, 沒所謂); 2. 把兩個 Class 擠進一個 unit 中, 這個方法我覺得甚劣, 因為兩個 Class 的程式碼均甚多, 並有繼續發展之勢。我嘗試過使用 #include 來把併合了的大怪物分柝, 但效果不好, 因為 #include 使用上有很多限制。 所以, 若能解決這個 Cyclic unit reference 問題, 這條題便自然迎刃而解了, 可是, 即使我到 Borland newsgroup 找解決方案, 都找不出第三個方案出來, 你有建議嗎?你可以考慮用Interface /(或先建立abstract 祖先類別), 不過用Interface雖然可有效降低類別間相互Reference的複雜度,但要付出較多的程式碼實做代價,對初學者而言可能不習慣 另一種解法就是往上一層建立抽象祖先,不過在寫法上可能和你說的第一種寫法差不到哪裡去 混心雜欲 棄修身~唉
------
唉~ |
hahalin
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:295 回覆:1698 積分:823 註冊:2002-04-14 發送簡訊給我 |
|
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言:我看懂了這段程式碼, 然而試用之後, 沒有效果(可選到全部 DataSets), 你試過嗎? -- 小卜子 發表人 - diviner 於 2004/05/17 16:06:55TMyDataSetProperty = class(TComponentProperty) private public function GetAttributes: TPropertyAttributes; override; procedure GetValues(Proc: TGetStrProc); override; end; procedure Register; begin RegisterComponents('Example', [TXClientDataSet]); RegisterPropertyEditor(TypeInfo(TDataSet), TXClientDataSet, 'XXXProperty', TMyDataSetProperty); end; function TMyDataSetProperty.GetAttributes: TPropertyAttributes; begin Result := inherited GetAttributes [paValueList]; end; procedure TMyDataSetProperty.GetValues(Proc: TGetStrProc); begin Designer.GetComponentNames(GetTypeData(TypeInfo(TXClientDataSet)),Proc); end;混心雜欲 棄修身~唉
------
-- 小卜子 |
speedup
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
引言: 我看懂了這段程式碼, 然而試用之後, 沒有效果(可選到全部 DataSets), 你試過嗎?我剛試寫一下,沒問題,將篩選出TXClientDataSet 附圖 unit XClientDataSet; interface uses SysUtils, Classes, DB, DBClient,TypInfo,DesignEditors,DesignIntf; type TXClientDataSet = class(TClientDataSet) private FXDataSet: TDataSet; procedure SetXDataSet(const Value: TDataSet); published property XDataSet:TDataSet read FXDataSet write SetXDataSet; end; TMyDataSetProperty = class(TComponentProperty) private public function GetAttributes: TPropertyAttributes; override; procedure GetValues(Proc: TGetStrProc); override; end; procedure Register; implementation procedure Register; begin RegisterComponents('Sample', [TXClientDataSet]); RegisterPropertyEditor(TypeInfo(TDataSet), TXClientDataSet, 'XDataSet', TMyDataSetProperty); end; { TXClientDataSet } procedure TXClientDataSet.SetXDataSet(const Value: TDataSet); begin FXDataSet := Value; end; { TMyDataSetProperty } function TMyDataSetProperty.GetAttributes: TPropertyAttributes; begin Result := inherited GetAttributes + [paValueList]; end; procedure TMyDataSetProperty.GetValues(Proc: TGetStrProc); begin Designer.GetComponentNames(GetTypeData(TypeInfo(TXClientDataSet)),Proc); end; end.混心雜欲 棄修身~唉
------
唉~ |
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言: 我剛試寫一下,沒問題,將篩選出TXClientDataSet ... 測試程式碼 ... procedure Register; begin RegisterComponents('Sample', [TXClientDataSet]); RegisterPropertyEditor(TypeInfo(TDataSet), TXClientDataSet, 'XDataSet', TMyDataSetProperty); end;原來是我打錯字, 上面紅色的部份, 我用了 String 的 TypeInfo, 當然是學習過程中從某處抄來的, 忘了換過來。現在完全正常了, 不好意思讓你麻煩了做個 Demo 出來。 謝謝您。 -- 小卜子
------
-- 小卜子 |
Diviner
初階會員 ![]() ![]() 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言: 你可以考慮用Interface /(或先建立abstract 祖先類別), 不過用Interface雖然可有效降低類別間相互Reference的複雜度,但要付出較多的程式碼實做代價,對初學者而言可能不習慣 另一種解法就是往上一層建立抽象祖先,不過在寫法上可能和你說的第一種寫法差不到哪裡去 混心雜欲 棄修身~唉是的, 我也考慮過這個方法, 所以現正學習使用 Interface, 希望 speedup 君以後再不吝賜教了。 其實, 我正是因為不希望 TXClientDataSet 日後因功能不斷增加而令程式碼不斷膨脹, 所以才分成兩個 Component, 再用各自的屬性連結起來, 這樣做, 你覺得作法如何? -- 小卜子
------
-- 小卜子 |
speedup
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
引言: 其實, 我正是因為不希望 TXClientDataSet 日後因功能不斷增加而令程式碼不斷膨脹, 所以才分成兩個 Component, 再用各自的屬性連結起來, 這樣做, 你覺得作法如何? -- 小卜子大哉問,我不清楚你要設計的元件功能,所已大概無法給啥建議,基本上解決問題的方法很多種,但好的架構的確有助於日後維護,如果有時間可以看看Design Pattern 或Refactor的書,搞不好你的問題已經被解決 另外你的問題有點頃向牽涉到實體分割的問題,這和Delphi的專案架構,與語言架構有點關係,如Delphi本身不支援Firend,兩個類別若要相互引用最簡單的方式就是放在同一個pas之中(但也代表這兩個Class關係太過複雜的確造成日後維護困然),重新檢視兩個類別的關係,重新設計成類似Delphi的(TDataSet/TDataSource/TDataLink or TControl/TWinControl or TCollection/TCollectionItem or TComponent)或許能夠解決問題。 舉個簡單的例子,這就有點類似在資料庫關聯中,通常若出現兩個多對多的表格時,這種狀況,通常會加入第三個表格使其變成兩個一對多的架構 相同的,你設計的架構若兩Class太複雜,可考慮將其中某部份切出成為負責連結關係的類別 混心雜欲 棄修身~唉
------
唉~ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |