Mike Torrettinni 198 Posted October 5, 2020 (edited) I prepared full example of a problem, but then I tried something different and it seem to be working OK, so, lets try with just quick confirmation: I have interposer for TCard so I can have custom data: TCard = class(Vcl.WinXPanels.TCard) strict private fDataType: TDataType; public property DataType: TDataType read fDataType write fDataType; end; Until today I never needed to create control that has interposer. But today I did and I started like this: and error occurs, of course: var vCard: TCard; ... vCard := CardPanel.AddNewCard; // ERROR: E2010 Incompatible types: 'Unit2.TCard' and 'Vcl.WinXPanels.TCard' vCard.DataType := x; so, I set it up like this - but I need to cast vCard all the time: var vCard: Vcl.WinXPanels.TCard; ... vCard := CardPanel.AddNewCard; // OK TCard(vCard).DataType := x; // BUT NOW I HAVE TO CAST IT ALL THE TIME BUT! now I figured out I can cast just initial CardPanel.AddNewCard line: var vCard: TCard; ... Vcl.WinXPanels.TCard(vCard) := CardPanel.AddNewCard; // OK vCard.DataType := x; // OK This seems correct. Is this the right way to do it? Or am I going into uncharted territory and will probably fail at some other point? Thanks! Edited October 5, 2020 by Mike Torrettinni Share this post Link to post
David Heffernan 2345 Posted October 5, 2020 (edited) Your interposer is effectively useless. When you call CardPanel.AddNewCard an instance of Vcl.WinXPanels.TCard is returned. No amount of casting can change that. You are just telling a big fat lie to the compiler. If you use as to cast then you will find out the runtime truth. They issue here is that you are trying to change the instantiated type of the cards. But declaring a new type of card doesn't achieve that since that code lives in the panel class. It's therefore the behaviour of the panel class that you need to modify. In order to get your card types created you should override GetCardClass. http://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.WinXPanels.TCustomCardPanel.GetCardClass You could do that with an interposer for TCardPanel. However, I wonder if perhaps the right thing to do is to stop using GUI controls to store data. GUI controls present data. They should not have knowledge of that data. Code outside of the control should be in charge of that. Edited October 5, 2020 by David Heffernan 3 1 Share this post Link to post
Guest Posted October 5, 2020 This !? Quote var vCard: TCard; ... Vcl.WinXPanels.TCard(vCard) := CardPanel.AddNewCard; // OK vCard.DataType := x; // OK Being able to do this, defeat the need for the intercepter/Interposer, remove it (and its overhead) and use usual well known classic inheritance. Share this post Link to post
Mike Torrettinni 198 Posted October 5, 2020 6 hours ago, Kas Ob. said: Being able to do this, defeat the need for the intercepter/Interposer, remove it (and its overhead) and use usual well known classic inheritance. 6 hours ago, David Heffernan said: However, I wonder if perhaps the right thing to do is to stop using GUI controls to store data. GUI controls present data. They should not have knowledge of that data. Code outside of the control should be in charge of that. Thanks guys, good point! The advice comes in at the right time, after discovering TCardPanel still has some quirks in Delphi 10.2.3. and my interposer is just adding on the points of failure. Share this post Link to post
Mike Torrettinni 198 Posted October 7, 2020 Update: As suggested, I removed the interposer class and implemented the Frame controller as suggested here: So instead of TCard control to hold custom data to identify which Data Frame it should show, Frame controller is responsible to connect TCard with appropriate Data Frame, so Main Form doesn't communicate with Data Frames anymore, as this is now Frame Controller's job. Works good, I'm happy with the correct solution 🙂 Share this post Link to post