xaf devexpress controls are disabled in DetailView - xaf

I'm viewing a DetailView when I click a button. My problem is I can't write anything to controls, they are disabled although I did:
view.ViewEditMode = ViewEditMode.Edit;
view.Model.AllowEdit = true;
that. What could be the cause?

The value for the particular view could have been modified in the module model.DesignedDiffs.xafml, or the same named file in the Web or Win module or in the Web or Win xafml module.
Start with the most descendant version, and check the properties for the view, and work back to the module's xafml.

Related

How to add a property to TTabSheet such that it can be used at design time with TPageControl

I would like to add "MyProperty" to TTabSheet and work with it at design time. However if I subclass it I fear I will need to also subclass TPageControl, since it internally creates/manages the TTabSheets.
I believe this would require duplicating the TTabSheet management code to reference TMyTabSheet instead of TTabSheet, since it will need to invoke TMyTabSheet.create. This feels like something I will regret when a new version of Delphi updates TPageControl and I forget to update TMyPageControl.
I am also researching "class helpers" as another option.
Does anyone have advice on how to best accomplish this?
Thanks!
Type Helpers are merely compile-time sugar, they would cause no effect over the already compiled code, that stock VCL is together with TPageControl and TForm. That is a dead-end.
However you have a slight misconception here that TPageControl... internally creates... the TTabSheets. Indeed, when you create the sheets by the means of TPageControl itself, like right-clicking it and selecting "New Tab" that si what happens. But when you create the living form object out of DFM file (or DFM resource in your compiled EXE) that is TForm itself that creates ALL the components, including both page control and its tabsheets.
Just see my answer at How to efficiently let a `ParentFont = False` child control to use same font name as parent? - that would show you how far it is about the owner - TForm, not about TPageControl or other parent components when it comes about selecting specific classes for the actual tabs or other elements..
So you are free to pursue subclassing tabsheets only.
Create the TMyTabsheet = class(TTabSheet) component
Create and install into IDE the design-time package that would introduce new subclassed tab sheet to Delphi Form Editor
In your form put the stock TPageControl and create all the needed tabs regular way
in IDE form Editor right-click over the form free space and in the menu do the "View As Text Alt-F12" command - you would see the text content of your form's DFM file
in those DFM sources find your tab sheets and change their stock TTabSheet class to be your derived sub-class
right-click the text editor and choose "View As Form Alt-F12" command
If all was done correct then Delphi would recreate the form with your new-class sheets now. Find your new properties in Object Inspector and change them.
Now switch to .Pas sources of your form and find the declarations of those tab sheets and change their type too. That is only required if you would have to access your new properties from the Delphi sources. If not you can leave their declaration as TTabSheet in pas-file as your class is direct descendant from it. You may leave those declarations as they were - but then you would have to add RegisterClass(TMyTabSheet); call into the very initialization section at the bottom of your unit, so when the form would construct itself out of the DFM it would be able to find the class implementation by the name. If you would change the declaration (at least one of those) then your form would automagically call all needed RegisterClass before streaming out of DFM. Choose any option you like.
Optionally and later, extend your design-time package to find and hijack IDE Form Editor's right-click menu for TPageControl and add "New My Subclassed Tab" command there. Just to avoid manual post-factum DFM editing. if you would do it often
This feels like something I will regret when a new version of Delphi updates TPageControl
After you created and tuned the form and saved it into DFM - it would be TForm that creates all the components out of the saved DFM-data, and that includes your tabs too. Unless very improbable event EMBT would kill the whole VCL streaming (made back in Delphi 1 in 1995) and redesign it from scratch (killing all the compatibility with existing Delphi sources at once), there should be no problem with forward compatibility with specifying your class in DFM. It is just the standard way VCL is designed - to get specific component types from the DFM.

Using BIND framework for two way data-binding in iOS

I'm trying to use BIND framework to bind a UITableView with UITextfield's which can edit the content.
I'm trying to achieve something very similar to how binding is done in Mac OSX. Bind a datasource with view, let the user make changes, on save the data is saved after validations.
Typically this is done by subscribing the delegate or observing the valueChanged event from textfield. I wanted to try out a new way to reduce this, that's how I came across BIND framework.
It encourages to use an MVVM framework, usually seen in .NET. Binding is as simple as mapping the keypath of model with the view component. But I'm finding it difficult to achieve to two way binding, from model to component and back.
BINDINGS(MHPersonNameViewModel,
BINDViewModel(name, ~>, textLabel.text),
BINDViewModel(ID, ~>, detailTextLabel.text),
nil);
Could anyone point me in the right direction.
This is a late answer, and not even really an answer to your question, but I hope it's still useful.
Take a look at https://github.com/mutech/aka-ios-beacon. This is a binding framework that integrates into Interface Builder and (by default) uses the view controller as root view model.
You don't have to write any code to initialize bindings. In your example, assuming that the view controller has (KVO compliant) properties "name" and "ID", you would just need to set the UILabel "text binding" properties to name and ID (you find the in the property panel in interface builder and enable bindings for the view controller (also in the properties panel).
And that should be all you have to do to establish bindings.
In versions up to 0.1.1 of AKABeacon, "enable bindings" is not yet there. In this case your view controller would have to inherit from AKAFormViewController.

How to debug or fix "Module has open descendants or linked modules" error?

I've had this long time problem that I can't view as text the main form for a project I inherited. Even if no other forms are open.
How can I debug the cause of this error message? What options do I have to fix it?
I found one related newsgroup post http://embarcadero.newsgroups.archived.at/public.delphi.ide/200906/0906193960.html but this only addresses the form inheritance cause, and doesn't explain anything about linked modules. I don't believe I'm using form inheritance.
I do have a DM (data module) for the project, and the form does load a couple of images from the dm through properties of a TTreeView on the form--does having a data module automatically mean I can never view as text a form in Delphi (aside from viewing the form as text in notepad)? It doesn't seem to matter whether my DM is open or closed in the IDE.
I also found one SO question with a related title (Module %s has open descendants or linked modules. can not reload) but the question itself and it's answer is not particularly relevant.
This is sometimes caused by a form that inherits from another form in your project (or the gallery) (known as Visual Form Inheritance in the documentation, IIRC). The IDE doesn't know how to find the base class for the form; it needs that opened before the descendant form. For instance, this can cause the same error if the unit containing TMyBaseForm isn't opened first in the IDE, particularly if the base (ancestor) unit is not included in the project first:
unit SpecialForm;
interface
uses
Forms, { all the other usual stuff }, BaseForm;
type
TMySpecialForm = class(TMyBaseForm)
private
public
end;
You can tell if this is the case by looking at your form's class declaration - if it descends from anything other than TForm, this is probably the cause of the error.
(Another instance of it happening is often when using a datamodule, because the base TDataModule .DFM isn't available. Attempting to view the datamodule .DFM as text will cause this error every time; the solution is to close your project and use an external editor such as Notepad or Notepad++ to edit the .dfm for your datamodule.)
I've had this issue occasionally, perhaps when I've used Frames, but my latest instance didn't involve Frames nor Data Modules nor inherited forms.
After an enormous amount of work creating a copy of the form (which copy didn't have the problem) and renaming the original unit and the form itself (which initially seemed to solve the problem), it turned out to be a live binding between forms.
Specifically, in my FMX application Form A has an options page with a TSpinBox that allows the user to set the minimum value for a TTrackBar on Form B (which was the form giving me grief). So the TSpinBox.Value was set to update the TTrackBar.Min field by means of a live binding. Closing Form A, or removing that live binding (and replacing it with an event handler to do the same thing) solved the problem.
I'd like to call upon the answer of Phillip J. Rayment and ADD that you don't have to have live binding to have this problem occur. It's sufficient to have custom control (class) of which you have an instance in another form. Then the RLink32 problem can appear and won't be solved until you close the form where you have the instance. The problem I experienced gave the following messages:
-RLink32 (during building)
-Access violation in module designide160.bpl` (if I made a modification to the problematic form)
-The module has open descendants or linked modules” error (if I tried to 'View as Form')

Delphi Designer, Is component inherited?

I'm writing a custom component editor, essentially similar to TActionList editor in that it allows creation of sub components.
Editor has buttons to add/delete components.
Now, I'd like to find out if selected component is inherited, so that I can disable the delete button.
I haven't found any such member in IDesigner or related interfaces.
If I just go ahead and delete by Designer.DeleteSelection(True); then I get an exception:
Selection contains a component, xxx, introduced in an
ancestor and cannot be deleted.
Which is not too bad, but I'd prefer to disable the delete button in the first place.
Ok, so apparently there is a way, by checking the TComponent.ComponentState for csAncestor, so:
csAncestor in ComponentState
And it's documented:
csAncestor - The component was introduced in an ancestor form. Only set if csDesigning is also set.

Hide VCL Classes

There are some program tools such as WinSpy++ which will allow you to hover over the Handle of any Control/Component and return the Class Name of that Handle. So for example, if I dropped a TMemo on a Delphi Form and compiled the Application, if I used WinSpy++ and hovered over the Application (above the Memo), it will reveal the Class Name of the Editor as TMemo.
Now, suppose I dont want anybody using such a program to determine the Components I am using in my Application, how would I prevent Class Names from showing up in a tool, such as WinSpy++?
I ask because I dont want anyone to easily create clones of any Applications I may create and release, if the Class Names of the Components I am using are discovered it would make their task easier because then they know what to use.
Simply put, how can I hide the Class Names of the VCL I use in my Delphi Application from external viewer tools like WinSpy++.
WinSpy++ can be found here: http://www.catch22.net/software/winspy
To add, I know I can custom derive these components to change the Class Names to my own, but their must be an easier way.
You could override CreateParams and put your own class name into Params.WinClassName. The default behaviour is implemented in TWinControl.CreateParams:
with Params do
...
StrPCopy(WinClassName, ClassName);

Resources