Adding data bindings via code

Is there a way I can add data bindings to objects that are created via code?

2 Likes

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?

2 Likes

That will do me nicely, thank you. It was the existence of the ‘form_refreshing_data_bindings’ event that I had missed.

1 Like

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.)

  1. Does Anvil still execute its own “equivalent” code?
  2. 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.

2 Likes

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?

A post was split to a new topic: Data bindings and repeating panel