TDateEdit cannot LiveBinding with a datasource bidirection - delphi

This is a simple question.
Start a multidevice App, place a TDateEdit and DBTable with a field containing TdateTime data. Then use LiveBinding designer link the data source field to TDateEdit.DateTime property. However, this link is unidirectional , The control DateEdit can accept the data from the Datasource, but cannot update the changes to the datasource. How to change the link to bidreiction???

There may be some things that are not clearly understood.
Normally a LiveBindings link will be bidirectional - so if you setup two TDateEdits and bind them together changing one should change the other, irrespective of which one you change.
It seems that what you are hoping is that changing the TField will update the data in the database table.
That's not typically how the Data Access components in Delphi work.
The TField is part of a TDataSet. The TDataSet has a Post method to write changes to the underlying data store, if that's supported.
The Data Access components are extremely powerrful and can cope with lots of different scenarios, and allow you to extended capabilities throguh exposed events as well as subclassing the components.
If you want to update your underlying data store you need to have a writeable TDataSet and you need to call Post on it to write.
I suggest you start off with some of the videos in Enbarcadero's YouTube channel about how to use the data acecss components. It's not difficult to do but beyond the scope of an answer here.

If you use the LiveBindings Wizard to hook the DateEdit with a field, it will hook it up bi-diretionally to a "virtual" SelectedDateTime property of the DateEdit. That property doesn't really exist in the TDateEdit but is used by the LiveBindings to map the separate Date and Time properties of the DateEdit.

Related

How to refence a DBGrid from another form

I have a mainForm with a DBGrid and I have a second form with a CheckListBox that shows all of the DBGrid columns for the user to choose. I need to reference in Form2 the DBGrid that I have in MainForm.
I would like this second form to handle all of the procedures connected to the dbdgrid columns , so that I can reuse it easily.
That was the idea, but I dod'nt find the way to pass the DBGrid reference.
Is it possible ?
Answering the question you asked, on your Form2, define a property
TForm2
[...]
private
FGrid : TDBGrid
public
property Grid : TDBGrid read FGrid write FGrid;
Then, after you've created an instance of TForm2, just do
Form2.Grid := MainForm.DBGrid1;
Then, on Form2, you can do anything valid you like to change Grid and the changes will be made to MainForm.DBGrid1.
Is it possible?
The question should rather be Is there a better way to achieve what I want?
Would it be maintainable if Form2 worked basically with a control from a different form? What if other forms would also need to hold references to components on other forms?
How hard would it be in a year to find a bug if controls are used over different forms?
Would such a solution match to the SOLID principles?
Answering these questions should help you to look for a different approach.
You should consider to separate UI and business logic. A TDBGrid seems to be a convenient way to get data from a database into your application but it violates the Single Responsibility Principle since it loads and displays data at the same time. Don't use it as a basic data provider inside your application. Perform the SQL queries from a deeper UI independant layer of your software. Store the results in containers and display them in all the ways you want in your different forms.

How can I set a TClientDataSet's data in the design view?

I have a TClientDataSet object that I've added to my form.
I've managed to define the fields through the object inspector. However, is there a way to define the data the TClientDataSet contains without doing it in code?
I've managed to do it by adding some AppendRecord statements to the ShowForm event; but I'd rather keep the definition of the TClientDataSet all in one place.
Prior to v10.2 (Seattle, Berlin, etc.), there were no facilities to do this.
You can store and load a file into the ClientDataSet or you can use the Assign Local Data (right click on the ClientDataSet) to load data from an existing source. However, you cannot append or edit the data from inside the IDE directly.
As of v10.2 (Tokyo) has recently added this as a feature.

dbctrlgrid delete and populate entries at runtime

I want to load the content of of dbctrlgrid at runtime (from database). So I encountered several challenges:
How to detect if the dbctrlgrid is empty and/or how to clear it.
How to put Tlabel and Tdbtext on the panel. The main problem seems to be to find the right parent. dbctrlgrid doesn't work. There is an object called Tdbctrlpanel which should work, but I don't know how to access it. I could not find it in properties or methods of Tdbctrlgrid.
Any code snipplet is welcome
To answer 1)
You don't query the TDBCtrlGrid, you query the underlying dataset; if it .IsEmpty the grid is empty.
When people start using data aware (grid) components they have the tendency to see that as the 'data container' that you can query and modify, but that is not the case. See it as a view on your underlying data with some built-in editors that modify that data. Then the 'same rules' apply to you as to these editors: update the underlying dataset.
To add controls to a TDBCtrlGrid you have to set the controls parent to the Panel property of the TDBCtrlGrid. The problem is that this property is protected. There are several ways to overcome this limitation. One is shown at Delphi About: Accessing protected members of a component
This is a common technique known to Delphi programmers as the 'protected hack'.

How to create a simple READ-ONLY TDataSet to access a memory structure

I have a memory structure which is (pretty much) static and read-only. I would like to present its data as a TDataSet descendent to enable me to use DB grids etc to view / report the data. I have no need of editing (in fact this must be prohibited). I've see this SO question and other advice that some home-rolled code 'has problems with bookmarks'. I really only want a simple solution and ideally this would be where I could create a simple 'virtual' table with my known field types and then be given an 'OnGetFieldData' event for each one. My other choice is to use a DevExpress TDxMemData in-memory table and populate it on changes in my data but this is less efficient and more messy. Is there any other solution?
Don't use TDataSet descendant, use LiveBindings instead. Your situation is exactly what they were created for. Here are some videos about their use: http://www.embarcadero.com/coderage/sessions

Is there a performance difference when adding Fields toboth TxxxQuery and TClientDataSet

When I use a TClientDataSet which is connected to a TxxxQuery component, I can add TFields to both components at design time. I recognized, when I don't specify the TFields in the TxxxQuery component, they are retrieved when the query is executed at runtime.
My questions is: Is there a performance difference when I add the TFields at design time to the TxxxQuery component?
When you add the fields at design time you get the strongly typed QueryName_FieldName fields you can use directly from code, skipping the name-based QueryName["FieldName"] lookup required if you don't have them.
From a performance stand-point the difference is most likely insignificant; From a language perspective having the fields added at design time provides better type safety, but only if you access the fields from code, and only if you use the QueryName_FieldName.Value syntax, not the named-based QueryName["FieldName"] syntax. If you use data-bound controls there's no difference.
I personally only add fields to TClientDataSet at design time when I need to use the client dataset without binding it to an other data source (ie: use it as a temporary table for reporting).

Resources