Is there a way I can add data bindings to objects that are created via code?
Yes! Data bindings are basically an abstraction in the form designer - you could create the same effect just by writing code. If I data-bind the text
property of a Label to the expression self.foo
, this is the equivalent of adding some code to the refreshing_data_bindings
event:
def form_refreshing_data_bindings (self, **event_args):
# This method is called when refreshing_data_bindings is called
self.label_1.text = self.foo
(The refreshing_data_bindings
event is triggered when you call the refresh_data_bindings()
method, or when you update the item
property on a form.)
If you have a data binding with write-back (eg on a TextBox), itâs as if youâve added the following code:
def text_box_1_lost_focus (self, **event_args):
# This method is called when the TextBox loses focus
self.foo = self.text_box_1.text
(When precisely a data binding writeback occurs is determined by the component. TextBoxes and TextAreas write back when they lose focus, whereas CheckBoxes and DropDowns write back on the change
event.)
Thatâs it! Thereâs nothing more magic about data bindings â itâs just an assignment, triggered off events. This means that you can do whatever you like in code, depending on what you want to do.
SoâŚwhat do you want to do? Is there a design pattern we can help you with?
That will do me nicely, thank you. It was the existence of the âform_refreshing_data_bindingsâ event that I had missed.
Suppose that I have written my own event-handling routines, as above, but also have some data bindings set in the designer. (E.g., I might do this in order to reformat or validate some of the formâs data items, while leaving other data items to follow Anvilâs default processing.)
- Does Anvil still execute its own âequivalentâ code?
- If it does, would the âequivalentâ code execute before my explicit code? Or after?
(Yes, I can experiment to find out. But this way, your intent gets documented for other Anvil users to read.)
If youâve set up data bindings in the designer, and you also handle the refreshing_data_bindings
event on your form, the data bindings happen after your refreshing_data_bindings
event handler. This means you can update bound variables before their values get displayed on the form.
Conversely, data binding writeback (ie when a componentâs value changes, and the bound variable is updated), happens before the event handler runs. This means that your event handler can safely use the bound variable (eg if I have a TextBox whose text
is bound to self.item['name']
, I can safely refer to self.item['name']
in my text_box_1_lost_focus
handler).
The important thing to remember is that everything you do with data bindings in the designer, you can do by handling the refreshing_data_bindings
event on your form and the change events on your components. The data bindings themselves are just a convenience.
Thank you. This timing looks like it will work really well for us.
Where this information becomes absolutely critical is in building a library for sanity-checking of inputs. One wants this to work with whatever code an Anvil developer has already built, so a âtheory-of-operationâ level of understanding becomes essential for any progress to be made. I greatly appreciate your efforts in this direction.
In some cases, it may be necessary to separate the bound (editable) variables from the ones that are ultimately used by the app, or stored for downstream use. But at least now I see how, in a practical sense, to do it.
Iâm not entirely sure how this applies to Radio Button Groups. Each button is its own object, with its own value and its own binding. But logically, for the Group as a whole, there is still only a single value (which may be None). Yet I do not see a Group object to which data can be bound. Is there Radio Button Group Data Binding example handy that I could look at?