{"id":1186,"date":"2012-09-20T22:49:36","date_gmt":"2012-09-20T12:49:36","guid":{"rendered":"http:\/\/www.malcolmgroves.com\/blog\/?p=1186"},"modified":"2014-06-10T22:00:16","modified_gmt":"2014-06-10T12:00:16","slug":"livebindings-in-xe3-updating-objects-via-an-adapter","status":"publish","type":"post","link":"http:\/\/www.malcolmgroves.com\/blog\/?p=1186","title":{"rendered":"LiveBindings in XE3: Updating Objects via an Adapter"},"content":{"rendered":"<p>Where I left off in <a title=\"LiveBindings in XE3: TAdapterBindSource and binding to Objects\" href=\"http:\/\/www.malcolmgroves.com\/blog\/?p=1084\">my last post<\/a>, we were able to bind our UI elements to an object, or indeed a collection of objects, by using the TAdapterBindSource combined with a TObjectBindSourceAdapter&lt;T&gt; or a TListBindSourceAdapter&lt;T&gt;.<\/p>\n<p>Over a few posts I want to drill a bit deeper into what happens when you make changes to those objects, specifically in this post, when you make changes via the bound controls. I&#8217;ll explore the notification system that LiveBindings uses in later posts.<!--more--><\/p>\n<p>Let&#8217;s stick with the simple example of 3 edit boxes bound to my TPerson, via a\u00a0TObjectBindSourceAdapter&lt;TPerson&gt;. We also want a TBindNavigator connected to the TAdapterBindSource.<\/p>\n<p>If you run the app and start editing a value in the edit box, you&#8217;ll notice the Navigator\u00a0changes\u00a0state.<\/p>\n<div id=\"attachment_1189\" style=\"width: 400px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapater1.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1189\" class=\"size-full wp-image-1189 \" title=\"updatingobjectviaadapater1\" alt=\"\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapater1.png\" width=\"390\" height=\"210\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapater1.png 390w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapater1-300x161.png 300w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapater1-297x159.png 297w\" sizes=\"auto, (max-width: 390px) 100vw, 390px\" \/><\/a><p id=\"caption-attachment-1189\" class=\"wp-caption-text\">Our Adapter in Edit mode. Note the Post and Cancel buttons are enabled?<\/p><\/div>\n<p>The Edit button becomes disabled, and the Post and Cancel buttons become enabled. A bit like a Dataset, right?<\/p>\n<blockquote class=\"pull-quote-right\"><p>In fact, this is the key analogy to use when you are thinking of Adapters: think of them like Datasets.<\/p><\/blockquote>\n<p>In fact, this is the key analogy to use when you are thinking of Adapters: think of them like Datasets. If you have a look at the methods and properties exposed on the adapters, you&#8217;ll spot many that are similar or exactly the same as TDataset, eg:<\/p>\n<ul>\n<li>A State property, of type TBindSourceAdapterState which has the values of seInactive, seBrowse, seEdit and seInsert<\/li>\n<li>BOF and EOF properties, along with Next, Prior, First and Last methods.<\/li>\n<li>Edit, Insert, Append, Post and\u00a0Cancel\u00a0methods.<\/li>\n<li>Before and After events for Insert, Open, Post, Scroll, and on and on&#8230;<\/li>\n<\/ul>\n<p>So your TListBindSourceAdapter&lt;T&gt; is almost like an object dataset for whatever type you specify in the T.<\/p>\n<p>Once you come to grips with this, what I&#8217;m about to say next will hopefully be obvious.<\/p>\n<p>When you edit a value in the Firstname edit box above, and then move over to edit the value in Lastname, because you have not yet called Post, those new values are not yet pushed back to your object. In fact they are buffered by the Adapter. Call Cancel (or press the Cancel button on the Navigator) and the values in the edit box will be restored to their original values.<\/p>\n<p>You can see this in the example project, I have a set of edit boxes bound using LiveBindings, and as a result they will show the values in the Adapter. I also have a set of Edit boxes which get their values direct from the underlying TPerson object. In the period between going into edit mode on the Adapter and changing some values, and before calling Post, you can see they have entirely different values. Calling Post pushes the changes back to the underlying object.<\/p>\n<blockquote class=\"pull-quote-left\">\n<div>This is pretty cool I think. A generic Object Dataset, providing buffered updates to my underlying objects.<\/div>\n<\/blockquote>\n<p>One more thing before I wrap up this post. We can access the\u00a0underlying\u00a0object to see it&#8217;s values, and we can access the not-yet-posted changes via LiveBindings, but how do we get those same not-yet-posted changes via code? Like I said, think of the Adapter like a dataset. The InternalAdapter property of \u00a0TAdapterBindSource will give you a reference to the TBindSourceAdapter descendant that&#8217;s being used.<\/p>\n<p>Once you have the Adapter, you can use FindField to get a reference to the individual fields like so:<\/p>\n<pre lang=\"delphi\">var\r\n\u00a0 Adapter : TBindSourceAdapter;\r\nbegin\r\n\u00a0 Adapter := AdapterBindSource1.InternalAdapter;\r\n\r\n\u00a0 lblAdapterFirstname.Text := Adapter.FindField('Firstname').GetTValue.ToString;\r\n\u00a0 lblAdapterLastname.Text := Adapter.FindField('Lastname').GetTValue.ToString;\r\n\u00a0 lblAdapterAge.Text := Adapter.FindField('Age').GetTValue.ToString;<\/pre>\n<p>NB: careful, referencing TAdapaterBindSource.Adapter, instead of InternalAdapter, will give you whichever Adapter is configured at design-time, not\u00a0necessarily\u00a0the one being used at runtime. In our last example, that will give you the TDataGeneratorAdapter with all those Lorem Ipsum values.<\/p>\n<p>There&#8217;s a sample project <a href=\"https:\/\/github.com\/malcolmgroves\/delphi-samples\" target=\"_blank\">on github<\/a> that illustrates the different values:<\/p>\n<div id=\"attachment_1190\" style=\"width: 401px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapter2.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1190\" class=\"size-full wp-image-1190\" title=\"updatingobjectviaadapter2\" alt=\"\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapter2.png\" width=\"391\" height=\"479\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapter2.png 391w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapter2-244x300.png 244w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2012\/09\/updatingobjectviaadapter2-297x363.png 297w\" sizes=\"auto, (max-width: 391px) 100vw, 391px\" \/><\/a><p id=\"caption-attachment-1190\" class=\"wp-caption-text\">Our sample app, showing the values in Edit mode, prior to a Post. Values from LiveBindings (top), the Adapter fields (middle) and direct from the object (bottom)<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Where I left off in my last post, we were able to bind our UI elements to an object, or indeed a collection of objects, by using the TAdapterBindSource combined with a TObjectBindSourceAdapter&lt;T&gt; or a TListBindSourceAdapter&lt;T&gt;. Over a few posts I want to drill a bit deeper into what happens when you make changes to [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[116],"tags":[64,19,48,89],"class_list":["post-1186","post","type-post","status-publish","format-standard","hentry","category-livebindings","tag-cbuilder","tag-delphi","tag-embarcadero","tag-livebindings"],"_links":{"self":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1186"}],"version-history":[{"count":27,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1186\/revisions"}],"predecessor-version":[{"id":1545,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1186\/revisions\/1545"}],"wp:attachment":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1186"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}