# Data Binding

#### <a class="anchor" id="bkmrk--13"></a>Description

DataBinding is the [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) framework mechanism to automatically distribute data items to interested consumers. The owner of data is the model component. It is the master in data distribution and sends and receives both data and control messages.

#### **Data Binding Fundamentals** 

##### <a class="anchor" id="bkmrk--15"></a>Binding Source

Data is organized in so called binding sources. A binding source is a group of logically related data items. The data items in a binding source can be hierarchically organized to compound data types and also supports lists natively. Data items can be of any native C/C++ type.

Data items might be grouped under the following aspects to binding sources

<div class="contents" id="bkmrk-logical-dependencies"><div class="contents"><div class="textblock">- **logical dependencies**   
    If data items have logical dependencies, these data items shall be put into the same binding source. In the data model of a radio station the station name is logically related to the frequency of the station. Both data items should only be updated once to avoid an inconsistent visualization of data.
- **update frequency**   
    data with equal update rates shall be grouped in a binding source. The speed data item should be put into the same binding source as the odometer data item. The update rate of both items is very different and the odometer value would be distributed in an unnecessary high data rate. Always the complete set of data in a binding source is updated.
- **data size**   
    Binding source data size shall be balanced. Defining too small binding sources creates overhead in the data binding system (a reference to a [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html) is stored in every component that receives the message). Defining too large binding sources might imply copying unnecessary data (as all binding source data needs to be copied to the [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html), the number of unchanged data that needs to be copied increases with the binding source data size).

</div></div></div>A binding source may contain any number of

<div class="contents" id="bkmrk-elementary-data-item"><div class="contents"><div class="textblock">- Elementary data items which can be 
    - scalar items of any C / C++ type
    - lists of elementary or compound items
- Compound data items (complex C / C++ types) which may contain again 
    - Compound data items
    - Elementary data items

</div></div></div>All data items in binding sources will be updated in an according [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html). Thus it is guaranteed that the data contained in a binding source will always be self consistent.

Bindings can only be defined on elementary data items and list items. It is not possible to define a binding on compound data items or single list items.

Binding sources are defined with the [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) XML Data Definition Language (XCDDL). From the data definition, source code is generated by CourierGenerator tool. XCDDL is also used by CGI Studio SceneComposer. Bindings between widget properties and data items can be specified in SceneComposer and will be automatically instantiated by [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) at runtime.

##### <a class="anchor" id="bkmrk--16"></a>Data Item Keys

[Courier::DataItemKey](http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga5dd39d92ef3bdbacc8187c4f7e835ab9 "Defines an alias representing the data item key. DataItemKey is an index to the global HierarchyNode ...") is the central identifier for data items in data binding. The keys are generated by code generation and can be used to address a specific data item in a binding source.

```
// bind SpeedWidget::Speed property to /CarStatus/Speed
ok = ok && <a class="code" href="http://dev.doc.cgistudio.at/APILINK/namespace_courier.html#a5e2cc7731143ac8a79d9175ad45be25e" title="Programmatically creates a binding between the specified data item and widget property. the life time of the binding object is controlled by the connected binding source and widget instance. As this function is creating a binding between a model data instance and a widget instance, it must be invoked in ViewComponent context only.">CreateBinding</a>(::Generated::ItemKey::CarStatus::SpeedItem,
                        "SpeedWidget",
                        "BindableSpeed",
                        widget);
```

[Courier::DataItemKey](http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga5dd39d92ef3bdbacc8187c4f7e835ab9 "Defines an alias representing the data item key. DataItemKey is an index to the global HierarchyNode ...") is the most efficient way to address a data item. Nevertheless there are two additional addressing schemes supported by data binding.

<div class="contents" id="bkmrk-ascii-string-path-e."><div class="contents"><div class="textblock">- ASCII string path e.g. /CarStatus/Speed
- Hash values calculated from the fully qualified ASCII string path

</div></div></div>Normal application developers will never encounter the need to use one of the alternative addressing schemes. Hash values are used to serialize binding information into the asset library and used internally only.

##### <a class="anchor" id="bkmrk--17"></a>Data Flow

Data is asynchronously distributed in the system with messages (see [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html)). Currently this is the only supported data access mechanism. Components receive data in [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html) messages. The components will hold a reference to the last received [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html) for each binding source. Thus components can read the latest data set synchronously from the message. If e.g. the view component opens a new View, the data for bound widget properties can be set immediately from the stored [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html) messages accordingly.

If the model receives new data, it will send the new set of data with a new [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html). The message not only carries modified, new data, but the complete set of the binding source data. For each data item the message carries a flag indicating if the item has been modified or not. For non-list data a single flag is sufficient information to indicate a change in data, for list data multiple types of changes may happen (e.g. adding, removing, modifying existing list items). Therefore additional information is necessary to inform controller and view about the nature of change. Courier::Internal::ListEventMsg is used to send list modification information from model to controller and view. [Courier::ListEventNotifier](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event_notifier.html "List event notifier. Convenience function for model component implementation. The class exposes a ful...") take over the job of sending Courier::Internal::ListEventMsg.

Components (controller / view) can also modify data items sent by the model. Again modified data is sent back in messages to the model. The [Courier::UpdateModelMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_update_model_msg.html "Update model message is responsible to carry requests to modify or update data back from view / contr...") messages are responsible to carry modified data items back to the model component. [Courier::UpdateModelMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_update_model_msg.html "Update model message is responsible to carry requests to modify or update data back from view / contr...") may carry multiple requests to change or update data for multiple binding sources.

On reception of an UpdateModelMsg the model component inspects the requests and, if the requests are accepted, modifies model data accordingly.

##### <a class="anchor" id="bkmrk--18"></a>Revision Numbers

All data binding messages carry a revision number of the data. The [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) framework maintains a revision number for each binding source data. Every time a [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html) is sent by the model, the according binding source revision number will be incremented. Requests from other components towards the model carry the revision number of the data the request has been issued with. If e.g. a widget requests to delete a list item, the model can check if the delete request has been made on the latest version of the data. If the revision number of the request is smaller than the revision number maintained in the model, the request might be ignored because widget and model have an inconsistent data state (see [Courier::BindingSourceRevisionStore](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_binding_source_revision_store.html "Binding source revision store. Maintains for each binding source a data revision number. The revision number is attached to all data binding messages from the model to other components. Change requests towards the model component carry the data revision number on which the changes should be done. It is up to the model to decide how change requests on old data revisions shall be handled.")).

##### <a class="anchor" id="bkmrk--19"></a>List Handling

DataBinding supports lists. As list data may be too large to send in messages, data binding supports fragmentation of lists. With fragmentation only list fragments of a defined number if list items are sent. Properties that can receive lists must be defined with [Courier::ListPropertyType](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html "Typed concrete list property type."). Following property definition defines a property to receive list types:

```
// property excepting lists of type TString
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(MenuEntries, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html" title="Typed concrete list property type.">Courier::ListPropertyType<FeatStd::String></a>, GetMenuEntries, SetMenuEntries)
CdaDescription("Test for properties bound to lists")
CdaCategory("List Test Properties")
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()
```

The [Courier::ListPropertyType](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html "Typed concrete list property type.") implements the [Courier::AsyncListInterface](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_async_list_interface.html "Defines an asynchronous list interface.") which the widget can use to request data from the list. The interface is - as the name suggests - asynchronous. The widget sends requests towards the list and the list responds to the requests with [Courier::ListEvent](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html "List event contains information about events happened on a list."). To receive list events, the widget has to register an event callback (see [Courier::ListEventHandler](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event_handler.html "Stores list event callback function and user data.")).

See <span style="color: rgb(230, 126, 35);">[List Handling](#bkmrk-list-handling%C2%A0)</span> for more details.

##### <a class="anchor" id="bkmrk--20"></a>Type Conversion

To establish a binding between a data item and a widget property, the data item type must match exactly the property type. To overcome that limitation, data binding defines the concept of type converters (see [Courier::TypeConverter](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_type_converter.html)). Type conversion works both for list and non-list data.

See chapter <span style="color: rgb(230, 126, 35);">[Type Converter](#bkmrk-type-converter%C2%A0)</span> for further information.

#### **Data Binding Cook Book** 

##### <a class="anchor" id="bkmrk--21"></a>Make Application Ready for Data Binding

In order to make your application ready for data binding, the following actions must be performed:

##### <a class="anchor" id="bkmrk--22"></a>Make Widget Properties Data Binding Aware

Widget properties have to be defined with CdaBindableProperty instead of CdaProperty. This will enable the property for data binding. Making a property bindable adds a small overhead to the property definition (approximately 4 bytes RAM per property - shared by all property instances).

If your widget is going to change the property value (e.g. a text input widget that changes the Text property), data binding must be informed about the change by using the PropertyModified method.

Widget properties handling lists are explained in <span style="color: rgb(230, 126, 35);">[List Handling](#bkmrk-list-handling%C2%A0)</span>

##### <a class="anchor" id="bkmrk--23"></a>Define Data Binding Model with XCDDL

Next is to define the application data model with XCDDL language - see <span style="color: rgb(230, 126, 35);">[Courier Data Definition Language XCDDL](#bkmrk-courier-data-definit)</span>.

##### <a class="anchor" id="bkmrk--24"></a>Implement the Application Model Component

See <span style="color: rgb(230, 126, 35);">[Model Component Sample Implementation](#bkmrk-model-component-samp)</span> for further details.

##### <a class="anchor" id="bkmrk--25"></a>Programmatically Establish Bindings

Bindings between widget properties and data items are normally defined in SceneComposer.

In order to do this, the specification file (XCDL or a XCDL derived description file) must be set. This can be set in SceneComposer by going to *File/Define application specification* and setting the following:

<div class="contents" id="bkmrk-specification%3A-xcdl-"><div class="contents"><div class="textblock">- Specification: XCDL or a XCDL derived description file (e.g. *BindingSources.xcddl* for *CourierSampleApp* )
- Search path: *&lt;cgi\_studio\_root&gt;/cgi\_studio\_courier/src*

</div></div></div>After these settings are made, the **Binding Property** of the widget must be set according to the requirements of the application.

Nevertheless bindings may also be implemented in the application code. [Courier::CreateBinding](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html#a5e2cc7731143ac8a79d9175ad45be25e "Programmatically creates a binding between the specified data item and widget property. the life time of the binding object is controlled by the connected binding source and widget instance. As this function is creating a binding between a model data instance and a widget instance, it must be invoked in ViewComponent context only.") does the trick.

```
// bind SpeedWidget::Speed property to /CarStatus/Speed
ok = ok && <a class="code" href="http://dev.doc.cgistudio.at/APILINK/namespace_courier.html#a5e2cc7731143ac8a79d9175ad45be25e" title="Programmatically creates a binding between the specified data item and widget property. the life time of the binding object is controlled by the connected binding source and widget instance. As this function is creating a binding between a model data instance and a widget instance, it must be invoked in ViewComponent context only.">CreateBinding</a>(::Generated::ItemKey::CarStatus::SpeedItem,
                        "SpeedWidget",
                        "BindableSpeed",
                        widget);
```

<div class="contents" id="bkmrk-bindings-exist-in-th"><div class="textblock"><div class="fragment">  
</div><dl class="note"><dt></dt><dd><p class="callout info">Bindings exist in the defined thread context. A binding from a data item to a widget property exists in the context of the view component and the thread the view component is executed in. Therefore programmatic definition of bindings must be done in the view component context only.</p>

</dd></dl></div></div>#### **Courier Data Definition Language XCDDL** 

##### <a class="anchor" id="bkmrk--26"></a>XCDDL fundamentals

XCDDL data definition contains compound data type and binding source definitions. Each distinct data entity in the binding source definition is called a *data item*. Data items can be of any C / C++ type as long as this type obeys certain criteria:

<div class="contents" id="bkmrk-the-type-must-define"><div class="contents"><div class="textblock">- the type must define a default constructor
- the type must be copyable (copy c-tor and assignment operators with public access)
- data binding has to perform certain type inspection on the data item types. Therefore the type shall not have protected or private inheritance for a base class

</div></div></div>The following XCDDL snippet defines a RadioStationData type based on a very simplified radio station model.

```
        <compound name="RadioStationData" uid="{8B61567E-F90E-4828-8EEE-E4FBD82515BD}">
            <comment>
                <![CDATA[]]>
            </comment>
            <item name="Name" type="RadioStationName" readonly="true" uid="{0EB7E841-CA1B-4B56-A755-0738924DA739}"/>
            <item name="Freq" type="Courier::Float" readonly="false" defaultValue="97.0" uid="{DDD5EFDA-EAAF-4B89-846D-6E70405C1B9D}"/>
            <item name="HasTMC" type="bool" readonly="true" defaultValue="false" uid="{8362FDC9-2C25-4986-A21B-3815F1B4344C}"/>
            <item name="Band" type="Band::Enum" validateType="false" readonly="false" defaultValue="Band::FM" uid="{6889C212-C0CE-4031-909D-9E5C7E07ADFA}"/>
        </compound>

```

The compound RadioStationData type is subsequently used to define a binding source Radio:

The binding source contains a data item for the current station, current TMC messages supplying station, and a list of preset stations.

```
        <bindingSource name="Radio" readonly="true" access="asynchronous" uid="{5361E13F-B66C-4CC9-97A7-B17CC615C195}">
            <comment>
                <![CDATA[]]>
            </comment>
            <item name="CurrentStation" type="RadioStationData" uid="{4FE2D8D6-E76F-45BE-BD22-01BC7A1352C9}">
                <comment>
                    <![CDATA[]]>
                </comment>
            </item>
            <item name="CurrentTMCStation" type="RadioStationData" uid="{d8e35b4b-b236-4814-bc04-4274245174d0}">
                <comment>
                    <![CDATA[]]>
                </comment>
            </item>
            <list name="Presets" type="RadioStationData" maxCount="6" allowEdit="true" allowRemove="true" allowAdd="true" uid="{BFCB2576-6DC0-44B5-877A-4E8DF0DD0A70}">
                <comment>
                    <![CDATA[]]>
                </comment>
            </list>
        </bindingSource>

```

Please refer to XCDDL schema documentation for further details.

##### <a class="anchor" id="bkmrk--27"></a>Sample data definition

```
<definition>
    <!--                                                        from namespace /Generated -->
    <include href="../../../../cgi_studio_courier/src/Courier/Platform/Types.xcdl" />
    <generator generate="true" location="DataModel">
        <namespace namespace="Generated"/>
        <header>
            <prolog file="../../../../cgi_studio_courier/CourierCopyright.txt" />
            <include file="FeatStd/Util/String.h"/>
            <include file="DataModel/BindingSourcesTypes.h"/>
      <include file="DataModel/RadioTypes.h"/>
          <include file="FeatStd/Util/StringBuffer.h" />
        </header>
        <source>
          <prolog file="../../../../cgi_studio_courier/CourierCopyright.txt" />
        </source>
    </generator>

    <types>
        <!-- 
        <compound name="RadioStationData" uid="{8B61567E-F90E-4828-8EEE-E4FBD82515BD}">
            <comment>
                <![CDATA[]]>
            </comment>
            <item name="Name" type="RadioStationName" readonly="true" uid="{0EB7E841-CA1B-4B56-A755-0738924DA739}"/>
            <item name="Freq" type="Courier::Float" readonly="false" defaultValue="97.0" uid="{DDD5EFDA-EAAF-4B89-846D-6E70405C1B9D}"/>
            <item name="HasTMC" type="bool" readonly="true" defaultValue="false" uid="{8362FDC9-2C25-4986-A21B-3815F1B4344C}"/>
            <item name="Band" type="Band::Enum" validateType="false" readonly="false" defaultValue="Band::FM" uid="{6889C212-C0CE-4031-909D-9E5C7E07ADFA}"/>
        </compound>
        <!-- 
    </types>

    <bindingSources>
        <!-- 
        <bindingSource name="Radio" readonly="true" access="asynchronous" uid="{5361E13F-B66C-4CC9-97A7-B17CC615C195}">
            <comment>
                <![CDATA[]]>
            </comment>
            <item name="CurrentStation" type="RadioStationData" uid="{4FE2D8D6-E76F-45BE-BD22-01BC7A1352C9}">
                <comment>
                    <![CDATA[]]>
                </comment>
            </item>
            <item name="CurrentTMCStation" type="RadioStationData" uid="{d8e35b4b-b236-4814-bc04-4274245174d0}">
                <comment>
                    <![CDATA[]]>
                </comment>
            </item>
            <list name="Presets" type="RadioStationData" maxCount="6" allowEdit="true" allowRemove="true" allowAdd="true" uid="{BFCB2576-6DC0-44B5-877A-4E8DF0DD0A70}">
                <comment>
                    <![CDATA[]]>
                </comment>
            </list>
        </bindingSource>
        <!-- 

        <bindingSource name="CarStatus" readonly="true" access="asynchronous" uid="{7F571FF5-F3F8-49DA-977F-745A4FAC1A7C}">
            <comment>
                <![CDATA[]]>
            </comment>
            <item name="Speed" type="Courier::UInt32" defaultValue="0" readonly="false" uid="{FBCADE39-6065-4B11-8F4E-D49C64DAD4B7}"/>
            <item name="RPM" type="Courier::UInt32" defaultValue="0" readonly="true" uid="{9A5D1EE6-DA77-49A9-B303-E958100C5CB2}"/>
        </bindingSource>

        <bindingSource name="TestValues" readonly="false" access="asynchronous" uid="{03ee17dc-5693-41a7-88f5-6407040b8e3d}">
            <comment>
                <![CDATA[]]>
            </comment>
            <item name="TestValue" type="Courier::Int32" defaultValue="0" readonly="false" uid="{70664678-C981-42AA-BE66-626834205C73}"/>
            <list name="TestValueList" type="Courier::UInt8" maxCount="10" allowAdd="false" allowEdit="false" allowRemove="false" uid="{6629b4a5-1618-4fea-a8c0-f1414424d2d4}"/>
        </bindingSource>
    
        <bindingSource name="SettingsMenu" access="asynchronous" uid="{6a240f30-285e-480c-9231-4f07e50b11cc}">
            <comment>
                <![CDATA[]]>
            </comment>
            <list name="MenuEntries" maxCount ="10" type ="FeatStd::String" windowSize="3" uid="{0ccf837b-9769-41b0-b8f8-111a7b272233}"/>
        </bindingSource>

        <messagePool bindingSourceRef="Radio" messagePoolsize="3" />
        <messagePool bindingSourceRef="CarStatus" messagePoolsize="3" />        
        <messagePool bindingSourceRef="SettingsMenu" messagePoolsize="8" />
        <messagePool bindingSourceRef="TestValues" messagePoolsize="3" />
    </bindingSources>
</definition>

```

#### **List Handling** 

##### <a class="anchor" id="bkmrk--28"></a>Description

[Courier::SyncListInterface](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_sync_list_interface.html "Abstract interface for synchronous access to list collections.") and [Courier::AsyncListInterface](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_async_list_interface.html "Defines an asynchronous list interface.") are the central access interfaces for lists. Handling lists split up handling lists in the model component and in widgets. The model component supplies list data and emits list events while the bound widget properties consume this data and events and emit list requests towards the model component.

##### **Widget List Handling** 

Widget properties must be defined as bindable property to enable them for data binding. List properties must be defined with [Courier::ListPropertyType](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html "Typed concrete list property type.").

The following example defines among other properties a list property of type [TString](http://dev.doc.cgistudio.at/APILINK/class_t_string.html "[DataBinding_RefTypeSample]").

```
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___widget_base.html#ga5fbdec0aa0a5d67f941ad5e4bef470da">CdaWidgetDef</a>(SampleWidget, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___m_e_s_s_a_g_i_n_g.html#ggac4e3f0853af916ef773e65d02a15c95dac1224e2f0bf57d4eede7026521a13aa8">Widget</a>)
    CdaDescription("Sample widget")
    CdaReadableName("Sample <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___m_e_s_s_a_g_i_n_g.html#ggac4e3f0853af916ef773e65d02a15c95dac1224e2f0bf57d4eede7026521a13aa8">Widget</a>")

    CdaProperties()
        // bool property that controls render enable / disable of the the attached scene graph node
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___behaviors_control.html#gga37959d0c8bd2f2c4ec4427a697be1365a0688e6a54d1bc2299be532bf9adf230d">Enabled</a>, bool, GetEnabled, SetEnabled)
        CdaDescription("Status: enabled or not")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()

        // property excepting lists of type TString
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(MenuEntries, Courier::ListPropertyType<FeatStd::String>, GetMenuEntries, SetMenuEntries)
        CdaDescription("Test for properties bound to lists")
        CdaCategory("List Test Properties")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()

        // property with reference type FeatStd::String
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(Label, FeatStd::String, GetLabel, SetLabel)
        CdaDescription("Test for properties bound to reference data types (FeatStd::String)")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()

        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(ValueList, Courier::ListPropertyType<Courier::UInt32>, GetValueList, SetValueList)
        CdaCategory("List Test Properties")
        CdaDescription("Test for properties bound to lists")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()

        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(GenericList, Courier::ListPropertyType<ListItemDataPresenter>, GetGenericList, SetGenericList)
        CdaCategory("List Test Properties")
        CdaDescription("generic list type")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()

        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(BoolList, Courier::ListPropertyType<bool>, GetBoolList, SetBoolList)
        CdaCategory("List Test Properties")
        CdaDescription("boolean list")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___widget_base.html#gaadabeed44f0653634b664191cd875742">CdaPropertiesEnd</a>()
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___widget_base.html#ga5b5647ca32644fc63627059a7f7fdef8">CdaWidgetDefEnd</a>()
```

The getter and setter function of a list property is very similar to any other property setter

```
const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html" title="Typed concrete list property type.">Courier::ListPropertyType<FeatStd::String></a>& GetMenuEntries() const {
    return mMenuEntriesProperty;
}

void SetMenuEntries(const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html" title="Typed concrete list property type.">Courier::ListPropertyType<FeatStd::String></a> &value) {
    mMenuEntriesProperty = value;
    mMenuEntriesProperty.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_generic_list_property_type.html#a511ffa91ad98e7f7c489bb9e55a49744" title="Set the callback function to be invoked when a list event happens.">SetEventCallback</a>(this, &SampleWidget::OnMenuEntryPropertyListEvent);
}
```

The only difference to standard setter and getter is that the setter will not only set the property, but also a callback function to receive events that are triggered by the list.

The setter does not invoke FrameworkWidget::PropertyChanged as list objects are read only data items. Only items of the list can be changed by the widget.

##### <a class="anchor" id="bkmrk--30"></a>List Events

[Courier::ListPropertyType](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_property_type.html "Typed concrete list property type.") exposes a [Courier::AsyncListInterface](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_async_list_interface.html "Defines an asynchronous list interface.") to the widget. The widget cannot synchronously read list elements but has to request list items from the list. The requested items then will be delivered with [Courier::ListEvent](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html "List event contains information about events happened on a list."). Courier::ListEventType::Enum defines other events a list might emit.

The following code shows a sample implementation for handling list events received by a list property.

```
void SampleWidget::OnMenuEntryPropertyListEvent(const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html" title="List event contains information about events happened on a list.">Courier::ListEvent</a> &listEvent)
{
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a> string;
    const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a> *itemString = listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#a8546d12f936218035e1b97625fc11076" title="Typed version of Item. Gets the item from the event object.">GetItem</a><<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a>>();
    if (itemString != 0) {    // if the list event carries a list item
        string = *itemString;
    }

    COURIER_LOG_INFO("received %s: newIndex=%u, oldIndex=%u, item=%s",
                      GetEventTypeName(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#a3a5bbba10dedf7127af37a0b9274a082" title="Gets the event type.">EventType</a>()),
                      listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(),
                      listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#a0a6065973c160588ef9e275ec4840885" title="contains the index of the item previous to the change in the list If the change/event type affected t...">OldIndex</a>(),
                      string.GetCString());

    bool ok = true;

    switch (listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#a3a5bbba10dedf7127af37a0b9274a082" title="Gets the event type.">EventType</a>()) {
        // ignore new fragment events, fragment events come on top of RequestedItem events
        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a55e2fd0a1f3b8d1c662423da7dbe7fd9">Courier::ListEventType::NewFragment</a>:
            break;

        // list item delivery bay - the order requested items come in is not specified
        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57acf184b2749a8420d95db121e6a61028a">Courier::ListEventType::RequestedItem</a>:
            SetMenuEntry(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(), string, false);
            break;

        // change event handling
        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57ae4fdc8e5a2ee798a354ed6523af43b16">Courier::ListEventType::ModifiedItem</a>:
            // change item in local list
            SetMenuEntry(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(), string, false);
            if (!listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#afdb007e3620a65e33c7d783b19e75433" title="Query if this object has a data item.">HasDataItem</a>()) {
                // if the event does not carry the modified data item, create a request for it
                ok = mMenuEntriesProperty.Request(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(), 1);
            }
            break;

        // add event handling
        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a47b1120a03e895efb8367d29a2f6a10a">Courier::ListEventType::AddedItem</a>:
            // insert item to local list
            SetMenuEntry(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(), string, true);
            if (!listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#afdb007e3620a65e33c7d783b19e75433" title="Query if this object has a data item.">HasDataItem</a>()) {
                // if the event does not carry the modified data item, create a request for it
                ok = mMenuEntriesProperty.Request(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(), 1);
            }
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57aea8f7d9a0ebd3abedae5d3c4e3e255ca">Courier::ListEventType::ListCleared</a>:
            mMenuEntries.Clear();
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a3a7e4ba56fce4b37a7792ae16df1be38">Courier::ListEventType::MovedItem</a>:
            ok = mMenuEntries.Move(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>(), listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#a0a6065973c160588ef9e275ec4840885" title="contains the index of the item previous to the change in the list If the change/event type affected t...">OldIndex</a>());
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a7b6df4c94c6dbb61af15e7b6caef4b54">Courier::ListEventType::RemovedItem</a>:
            ok = mMenuEntries.RemoveAt(listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#acf691e05014f3f72761d38d3c50002fe" title="Denotes the index of the item affected by the event.">NewIndex</a>());
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57ada81eaf114f442ab72d6df58ca4784b3">Courier::ListEventType::ItemCountChanged</a>:
        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a79ba07cece44c29a9048279407b2457f">Courier::ListEventType::RefreshList</a>:
            ResetMenuEntries();
            ok = mMenuEntriesProperty.Request(0, mMenuEntriesProperty.Count());
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___layout.html#gga143e31a12d442971ea2cbcda11cf35e3a6325ea46e8f4c69da2da6ccae1f7c4a6" title="The image will not be stretched; it will be rendered in its original size. If the available space is ...">Courier::ListEventType::None</a>:
        default:
            COURIER_DEBUG_FAIL();
            break;
    }

    if (!ok) {
        COURIER_LOG_WARN("error processing list event");
    }

    if (listEvent.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_list_event.html#a3a5bbba10dedf7127af37a0b9274a082" title="Gets the event type.">EventType</a>() != <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a55e2fd0a1f3b8d1c662423da7dbe7fd9">Courier::ListEventType::NewFragment</a>) {
        // we mirrored the complete list if count matches and no empty string
        // is in menu entries. if we achieved this state, log all entries and
        // send notification message (will trigger next test)
        bool complete = mMenuEntries.Count() == mMenuEntriesProperty.Count();
        for (FeatStd::UInt32 i = 0; complete && i < mMenuEntries.Count(); ++i) {
            complete = *mMenuEntries[i].GetCString() != 0;
        }
        if (complete) {
            for (FeatStd::UInt32 i = 0; i < mMenuEntries.Count(); ++i) {
                <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_i_a_g_n_o_s_t_i_c_s.html#gacd98a31ecfbf5e78f64662726ebef6dd">COURIER_LOG_DEBUG</a>("MenuItem %02u %s", i, mMenuEntries[i].GetCString());
            }

            // state has been updated -> tell the world about it
            // in this sample the message will trigger the execution of the next test step in SampleAppViewController
            SampleWidgetMenuEntriesSetMsg *msg = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___p_l_a_t_f_o_r_m.html#ga49830e96f37f0b76cc63f52696ceb119">COURIER_MESSAGE_NEW</a>(SampleWidgetMenuEntriesSetMsg)();
            if (msg != 0) {
                (void) msg->Post();
            }
        }
    }
}
```

#####   
**Model Component List Handling** 

##### <a class="anchor" id="bkmrk--31"></a>List Event

Lists can undergo multiple types of changes. List changes are therefore always propagated in two steps

<div class="contents" id="bkmrk-send-the-binding-sou"><div class="contents"><div class="textblock">- send the binding source data that contains the modified list
- send one or more notifications that tell about what changes have been applied on the lists

</div></div></div>##### <a class="anchor" id="bkmrk--32"></a>Enforce a refresh of list content

If the list content has changed on a large scale, issuing a refresh event triggers all data clients to reset their state and to reload list contents.

```
bool SampleAppModelComponent::RefreshListTest()
{
    bool ok;

    // initialize the list
    ok = SetupMenuEntries();

    // menu entries are sent in fragments -> copy the modified data to the fragment before sending the update
    ok = ok && (*mSettingsMenuData).mMenuEntries.ReadFragment(mSettingsMenu, 0);

    // send data to the view
    ok = ok && mSettingsMenuData.SendUpdate();

    // use a list event notifier to send the list event
    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // trigger widget model refresh - refresh indicates that the widgets bound to the list shall
    // refresh all state related to this list
    ok = ok && settingsMenuNotifier.NotifyRefreshList();

    return ok;
}
```

##### <a class="anchor" id="bkmrk--33"></a>Adding a list item

If a list item has been added, the change must be propagated to all clients of the list.

```
bool SampleAppModelComponent::AddItemTest()
{
    bool ok;

    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // add a menu item
    ok = mSettingsMenu.InsertAt(0, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a>("New menu entry"));

    // menu entries are sent in fragments -> copy the modified data to the fragment before sending the update
    ok = ok && (*mSettingsMenuData).mMenuEntries.ReadFragment(mSettingsMenu, 0);

    // mark the item as modified - this will cause an automatic increment of the data revision number
    // of the binding source. Alternatively the data revision can also be manually incremented 
    // with BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    ok = ok && mSettingsMenuData.MarkItemModified(ItemKey::SettingsMenu::MenuEntriesItem);

    // Send the updated list. note - we did not set the update bit of SettingsMenu::MenuEntriesItem
    // as this would trigger a RefreshList (i.e. the list data item received a new value and this
    // can only result in a refresh of the list in the widget
    ok = ok && mSettingsMenuData.SendUpdate();

    // *after* sending the data, we tell about the changes in the list. In this case we added an
    // item at position 0
    ok = ok && settingsMenuNotifier.NotifyItemAdded(0);

    return ok;
}
```

##### <a class="anchor" id="bkmrk--34"></a>Modifying a list item

If a list item has been modified, the change must be propagated to all clients of the list.

```
bool SampleAppModelComponent::ModifyItemTest()
{
    bool ok;
    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // modifiy the list item at index 0 and send the updated data & copy to fragment
    mSettingsMenu[0] = "modified list entry";

    // update the fragment
    ok = (*mSettingsMenuData).mMenuEntries.ReadFragment(mSettingsMenu, 0);

    // mark the item as modified - this will cause an automatic increment of the data revision number
    // of the binding source. Alternatively the data revision can also be manually incremented 
    // with BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    ok = ok && mSettingsMenuData.MarkItemModified(ItemKey::SettingsMenu::MenuEntriesItem);

    ok = ok && mSettingsMenuData.SendUpdate();

    // tell which items have been changed (again - after the data has been updated)
    ok = ok && settingsMenuNotifier.NotifyItemModified(0);

    return ok;
}
```

##### <a class="anchor" id="bkmrk--35"></a>List item count change

If a list item has been appended at the end of the list, the change must be propagated to all clients of the list.

```
bool SampleAppModelComponent::ChangeItemCountTest()
{
    bool ok;
    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // add items at the *end* of the list, send the modified list, and tell what changed in the list
    ok = mSettingsMenu.PushBack(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a>("new entry"));

    // not to forget to update the list item count in the fragment too
    (*mSettingsMenuData).mMenuEntries.UpdateListItemCount(mSettingsMenu.Count());

    // mark the item as modified - this will cause an automatic increment of the data revision number
    // of the binding source. Alternatively the data revision can also be manually incremented 
    // with BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    ok = ok && mSettingsMenuData.MarkItemModified(ItemKey::SettingsMenu::MenuEntriesItem);

    ok = ok && mSettingsMenuData.SendUpdate();
    ok = ok && settingsMenuNotifier.NotifyItemCountChanged();

    return ok;
}
```

##### <a class="anchor" id="bkmrk--36"></a>List item has been moved

If a list item has been moved from one position to the other in the list, the change must be propagated to all clients of the list

```
bool SampleAppModelComponent::MoveItemTest()
{
    bool ok;
    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // move item at index 1 to index 0
    ok = mSettingsMenu.Move(0, 1);

    // update the fragment
    ok = ok && (*mSettingsMenuData).mMenuEntries.ReadFragment(mSettingsMenu, 0);


    // mark the item as modified - this will cause an automatic increment of the data revision number
    // of the binding source. Alternatively the data revision can also be manually incremented 
    // with BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    ok = ok && mSettingsMenuData.MarkItemModified(ItemKey::SettingsMenu::MenuEntriesItem);

    // send update and notify about the list change
    ok = ok && mSettingsMenuData.SendUpdate();
    ok = ok && settingsMenuNotifier.NotifyItemMoved(0, 1);

    return ok;
}
```

##### <a class="anchor" id="bkmrk--37"></a>List item has been removed

If a list item has been removed from the list, the change must be propagated to all clients of the list.

```
bool SampleAppModelComponent::RemoveItemTest()
{
    bool ok;
    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // remove item at index 0
    ok = mSettingsMenu.RemoveAt(1);

    // update the fragment
    ok = ok && (*mSettingsMenuData).mMenuEntries.ReadFragment(mSettingsMenu, 0);


    // mark the item as modified - this will cause an automatic increment of the data revision number
    // of the binding source. Alternatively the data revision can also be manually incremented 
    // with BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    ok = ok && mSettingsMenuData.MarkItemModified(ItemKey::SettingsMenu::MenuEntriesItem);

    ok = ok && mSettingsMenuData.SendUpdate();
    ok = ok && settingsMenuNotifier.NotifyItemRemoved(0);

    return ok;
}
```

##### <a class="anchor" id="bkmrk--38"></a>List has been cleared

If a list has been cleared, the change must be propagated to all clients of the list.

```
bool SampleAppModelComponent::ClearListTest()
{
    bool ok;
    ListEventNotifier settingsMenuNotifier(Generated::ItemKey::SettingsMenu::MenuEntriesItem);

    // clear the list
    mSettingsMenu.Clear();

    // update the fragment
    ok = (*mSettingsMenuData).mMenuEntries.ReadFragment(mSettingsMenu, 0);

    // mark the item as modified - this will cause an automatic increment of the data revision number
    // of the binding source. Alternatively the data revision can also be manually incremented 
    // with BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    ok = ok && mSettingsMenuData.MarkItemModified(ItemKey::SettingsMenu::MenuEntriesItem);

    // update and notify the other components
    ok = ok && mSettingsMenuData.SendUpdate();
    ok = ok && settingsMenuNotifier.NotifyListCleared();
    return ok;
}
```

##### <a class="anchor" id="bkmrk--39"></a>List Request Handling

```
bool SampleAppModelComponent::OnSettingsMenuListRequest(const Request &request)
{
    // handle requests towards SettingsMenuList

    COURIER_LOG_INFO("request %d, newIndex=%u, oldIndex=%u", request.RequestType(), request.NewIndex(), request.OldIndex());

    // determine if the request is based on an outdated data revision
    // this sample will gracefully ignore change requests on outdated data base. the only request allowed on outdated
    // data is the request for a new list fragment
    // request.DataRevision returns the revision number in which context the request has been done by the view component
    // BindingSourceRevisionStore::GetRevision returns the current revision number of the binding source in the model
    bool outDated = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga0102e7a03a62e0bbf06912d44b7eb070">Courier::CompareRevisions</a>(request.DataRevision(), BindingSourceRevisionStore::GetRevision(request.ItemKey())) < 0;
    if (outDated && request.RequestType() != <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a55e2fd0a1f3b8d1c662423da7dbe7fd9">ListRequestType::NewFragment</a>) {
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_i_a_g_n_o_s_t_i_c_s.html#gacd98a31ecfbf5e78f64662726ebef6dd">COURIER_LOG_DEBUG</a>("received out dated request (%u vs. %u", 
                           request.DataRevision(), 
                           BindingSourceRevisionStore::GetRevision(request.ItemKey()));
        return false;
    }

    // will be set if the request requires an update to be sent
    bool requiresUpdate = false;
    // will be set if the request caused a change in the data model
    bool listChanged = false;

    // modify list data according to the request type
    switch(request.RequestType()) {
        case ListRequestType::AddItem: {
            // add a new list item at NewIndex
            const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a> *newItem = request.GetItem<<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a>>();
            requiresUpdate = newItem != 0 && mSettingsMenu.InsertAt(request.NewIndex(), *newItem);
            break;
        }

        case ListRequestType::ModifyItem: {
            // existing list item gets modified at index NewIndex
            const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a> *newItem = request.GetItem<<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_string.html">FeatStd::String</a>>();
            if (newItem != 0 && request.NewIndex() < mSettingsMenu.Count()) {
                mSettingsMenu[request.NewIndex()] = *newItem;
                listChanged = true;
            }
            break;
        }

        case ListRequestType::ClearList:
            // clear the list
            mSettingsMenu.Clear();
            listChanged = true;
            break;

        case ListRequestType::MoveItem:
            // move a list item to a new index
            listChanged =  mSettingsMenu.Move(request.NewIndex(), request.OldIndex());
            break;

        case ListRequestType::RemoveItem:
            // remove a list item
            listChanged = mSettingsMenu.RemoveAt(request.NewIndex());
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gga7e8c2538a212673b9e59b6941a54cb57a55e2fd0a1f3b8d1c662423da7dbe7fd9">ListRequestType::NewFragment</a>:
            // explicit request for a new list fragment
            requiresUpdate = true;
            break;

        case ListRequestType::PrefetchItems:
            // nothing to do here - the list is not prefetching
            // this request causes normally the model to read data from external
            // data sources. it prepares near future NewFragment requests. for example
            // a list widget might send prefetch request for next list pages when the user
            // scrolls down.
            // No events are sent back to the view component in response to the prefetch
            // request.
            break;

        case <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___layout.html#gga143e31a12d442971ea2cbcda11cf35e3a6325ea46e8f4c69da2da6ccae1f7c4a6" title="The image will not be stretched; it will be rendered in its original size. If the available space is ...">ListRequestType::None</a>:
        default:
            COURIER_DEBUG_FAIL();
            break;
    }

    if (listChanged) {
        // if the list got modified, increase data revision number
        (void) BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    }

    // return true if the request requires updates to be sent
    return requiresUpdate || listChanged;
}
```

#### **Type Converter** 

To establish a binding between a data item and a widget property, the data item type must match exactly the property type.

To overcome that limitation, data binding defines the concept of type converters (see [Courier::TypeConverter](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_type_converter.html)). A type converter is nothing more than two functions that convert from type A to B and vice versa. Thus the overhead of a type converter is quite low (approximately 8 bytes RAM per type converter and the code size of the two conversion functions).

```
struct DateTime {
    Courier::UInt mHour;
    Courier::UInt mMinute;
    Courier::UInt mSecond;

    Courier::UInt mDay;
    Courier::UInt mMonth;
    Courier::UInt mYear;
};

// DateTime --> std::string
bool TypeConvert(std::string &str, const DateTime &dateTime)
{
    Courier::Char buf[50];
    sprintf(buf, "%02u:%02u:%02u %u.%u.%u", dateTime.mHour, dateTime.mMinute,
            dateTime.mSecond, dateTime.mDay, dateTime.mMonth, dateTime.mYear);
    str = buf;
    return true;
}

// std::string --> DateTime
bool TypeConvert(DateTime &dateTime, const std::string &str)
{
    Courier::Int n = sscanf(str.c_str(), "%02u:%02u:%02u %u.%u.%u", &dateTime.mHour, &dateTime.mMinute,
                            &dateTime.mSecond, &dateTime.mDay, &dateTime.mMonth, &dateTime.mYear);
    return n == 6;
}

bool RegisterMyTypeConverters()
{
    using Courier::TypeConverter;
    // create a TypeConverter instance to make it known to Courier DataBinding
    static TypeConverter<std::string, DateTime> converter;

    return true;
}

```

[Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) ships already with a set of standard type converters. To activate the converters the application must invoke [Courier::RegisterStdTypeConverters](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html#a7be6d0e4325230b79f6dbae25125e059).

Type converters should be created at system startup time only. The list of type converters is not synchronized.

#### **Reference Types** 

To avoid multiple instances and copying of large buffers like images, messages can also reference types. A reference type does not store data intrinsically, but keeps only a reference to the data buffer. Needless to say that in a multi threaded configuration (e.g. model component and view component are executed in different threads) the access to the reference data must be synchronized. The [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) SampleApplication implements a reference type for UTF8 encoded strings which might act as a starting point for application specific reference types.

#### **Model Component Sample Implementation** 

##### <a class="anchor" id="bkmrk--40"></a>Model Component Implementation

The data model defined in <span style="color: rgb(230, 126, 35);">[Courier Data Definition Language XCDDL](#bkmrk-xcddl-fundamentals)</span> is hosted by CourierSampleApplication in the following class

```
class SampleAppModelComponent : public Courier::ModelComponent {
    public:
        SampleAppModelComponent();
        virtual ~SampleAppModelComponent();

        bool Init();

    private:
        Courier::Int32 mSpeedDelta;
        Courier::UInt32 mDataBindingTestCount;
        Courier::DataItemContainer<Generated::RadioDataBindingSource> mRadioData;
        Courier::DataItemContainer<Generated::CarStatusDataBindingSource> mCarStatus;
        Courier::DataItemContainer<Generated::SettingsMenuDataBindingSource> mSettingsMenuData;
        Courier::DataItemContainer<Generated::TestValuesDataBindingSource> mTestValuesData;
        // store for complete menu items list
        Courier::FixedSizeList<FeatStd::String, Generated::SettingsMenuData::cMenuEntriesMax> mSettingsMenu;

        void OnSpeedChanged(Courier::UInt32 newSpeed);
        void OnAutoPilot();

        void OnStartupMsg();

        bool OnSettingsMenuListRequest(const Courier::Request &request);
        bool OnTestValuesRequest(const Courier::Request &request);

        bool UpdateListFragment(Courier::DataItemKey listItemKey, Courier::UInt32 fragmentStart);
        bool SendBindingSourceUpdate(Courier::DataItemKey bindingSourceKey);

        virtual bool OnMessage(const Courier::Message & msg);
        void OnUpdateModelMsg(const Courier::UpdateModelMsg *msg);
};

```

The class defines data members for the binding sources defined in XCDDL. The data types generated from XCDDL can, but don't have to be used in the model component.

```
        Courier::DataItemContainer<Generated::RadioDataBindingSource> mRadioData;
        Courier::DataItemContainer<Generated::CarStatusDataBindingSource> mCarStatus;
        Courier::DataItemContainer<Generated::SettingsMenuDataBindingSource> mSettingsMenuData;
        Courier::DataItemContainer<Generated::TestValuesDataBindingSource> mTestValuesData;
        // store for complete menu items list
        Courier::FixedSizeList<FeatStd::String, Generated::SettingsMenuData::cMenuEntriesMax> mSettingsMenu;

```

The SettingsMenuDataBindingSource contains a fragment list. Therefore the binding source data types can only store a fragment of the menu item list. The complete list must be stored somewhere else (in the sample in a FixedSizeList container).

[Courier::DataItemContainer](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_container.html "Data item container is a helper function for model implementation. the DataItemContainer holds all da...") is a convenience class to handle binding source data.

As in any other component messages are received with [Courier::Component::OnMessage](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_component.html#a50ec4f7ca1e9556729d0d3323e3a3c88) method.

```
// ------------------------------------------------------------------------
bool SampleAppModelComponent::OnMessage(const Courier::Message & msg)
{
    // central message bay for the SampleAppModelComponent

    switch(msg.GetId()) {
        case StartupMsg::ID:
            OnStartupMsg();
            break;

        case UpdateModelMsg::ID:
            // request from controller / view to change model data
            OnUpdateModelMsg(message_cast<const UpdateModelMsg*>(&msg));
            break;

        case ToggleAutoPilotMsg::ID:
            // external request (normally triggered by hitting the 'a' key)
            OnAutoPilot();
            break;

        case SpeedMsg::ID: {
            // external speed value message (triggered normally by pressing keys 0-9
            const SpeedMsg * speedMsg = message_cast<const SpeedMsg *>(&msg);
            if(speedMsg != 0) {
                OnSpeedChanged(speedMsg->GetSpeed());
            }
            break;
        }

        // corresponding widget code was removed
        //case NextDataBindingTestMsg::ID: {
        //    // test execution control message. sent from the SampleViewController
        //    // run the next test step
        //    bool result = RunDataBindingTests();
        //    // respond with DataBindingTestExecutedMsg
        //    DataBindingTestExecutedMsg *theMsg = COURIER_MESSAGE_NEW(DataBindingTestExecutedMsg)(result);
        //    if (theMsg != 0) {
        //        (void) theMsg->Post();
        //    }
        //    break;
        //}

        default:
            break;
    }
    return false;
}

```

The OnMessage method both receives external data input (in sample application SpeedMsg or ToggleAutoPilotMsg) and messages from other components (controller and view). The most important message from other components is [Courier::UpdateModelMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_update_model_msg.html "Update model message is responsible to carry requests to modify or update data back from view / contr..."). This message carries requests from the components that the model shall process.

Of course it is up to the application developer to define any number of additional messages that the model can receive from other components (like the NextDataBindingTestMsg that triggers test execution).

Processing of [Courier::UpdateModelMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_update_model_msg.html "Update model message is responsible to carry requests to modify or update data back from view / contr...") takes place in OnUpdateModelMsg.

```
// ------------------------------------------------------------------------
void SampleAppModelComponent::OnUpdateModelMsg(const UpdateModelMsg *msg)
{
    using namespace Generated;

    // controller / view request changes in the model data. An UpdateModelMsg
    // may contain multiple change requests for multiple binding sources.
    // the ChangeTracker helps to keep track of the changes and takes over the
    // house keeping tasks like list fragment update, sending of DataItemMsg
    // with modified data, and list event notifications.
    ChangeTracker changeTracker(this,
                                &SampleAppModelComponent::UpdateListFragment,
                                &SampleAppModelComponent::SendBindingSourceUpdate);

    bool ok = true;
    // for every request in the UpdateModelMsg
    for (UInt32 i = 0; ok && i < msg->RequestCount(); ++i) {
        // get request from UpdateModelMsg
        Request request(msg->GetRequest(i));
        switch (request.BindingSourceKey()) {
            case ItemKey::SettingsMenuItem:
                if (OnSettingsMenuListRequest(request)) {
                    ok = changeTracker.RegisterChange(i, request);
                }
                break;

            case ItemKey::TestValuesItem:
                if (OnTestValuesRequest(request)) {
                    ok = changeTracker.RegisterChange(i, request);
                }
                break;

            case ItemKey::RadioItem:
                break;

            default:
                // unknown binding source
                COURIER_DEBUG_FAIL();
                ok = false;
                break;
        }
        if (!ok) {
            COURIER_LOG_ERROR("update request failed");
        }
    }

    // trigger send of DataItemMsg and ListEvent notifications for the requested
    // changes. changeTracker keeps track which binding source data to update and
    // which list events to send.
    if (!changeTracker.SendChanges(msg)) {
        COURIER_LOG_ERROR("failed to update data");
    }
}

```

The processing of requests for the TestValues binding source is done in SampleAppModelComponent::OnTestValuesRequest.

```
// ------------------------------------------------------------------------
bool SampleAppModelComponent::OnTestValuesRequest(const Courier::Request &request)
{
    // handle request towards TestValues binding source data

    bool appliedChange;
    switch(request.ItemKey()) {
        case ItemKey::TestValues::TestValueItem:
            appliedChange = mTestValuesData.SetValue(request.ItemKey(), request.GetItemValue());
            COURIER_LOG_INFO("TestValue->%u", (*mTestValuesData).mTestValue);
            break;

        case ItemKey::TestValues::TestValueListItem:
            // as the list is read only (allowAdd=false etc.) only NewFragment and Prefetch
            // request may come in.
            appliedChange = true;
            break;

        default:
            appliedChange = false;
            break;
    }

    return appliedChange;
}

```

Full handling of a modifiable list is implemented in SampleAppModelComponent::OnSettingsMenuListRequest.

```
// ------------------------------------------------------------------------
bool SampleAppModelComponent::OnSettingsMenuListRequest(const Request &request)
{
    // handle requests towards SettingsMenuList

    COURIER_LOG_INFO("request %d, newIndex=%u, oldIndex=%u", request.RequestType(), request.NewIndex(), request.OldIndex());

    // determine if the request is based on an outdated data revision
    // this sample will gracefully ignore change requests on outdated data base. the only request allowed on outdated
    // data is the request for a new list fragment
    // request.DataRevision returns the revision number in which context the request has been done by the view component
    // BindingSourceRevisionStore::GetRevision returns the current revision number of the binding source in the model
    bool outDated = Courier::CompareRevisions(request.DataRevision(), BindingSourceRevisionStore::GetRevision(request.ItemKey())) < 0;
    if (outDated && request.RequestType() != ListRequestType::NewFragment) {
        COURIER_LOG_DEBUG("received out dated request (%u vs. %u",
                           request.DataRevision(),
                           BindingSourceRevisionStore::GetRevision(request.ItemKey()));
        return false;
    }

    // will be set if the request requires an update to be sent
    bool requiresUpdate = false;
    // will be set if the request caused a change in the data model
    bool listChanged = false;

    // modify list data according to the request type
    switch(request.RequestType()) {
        case ListRequestType::AddItem: {
            // add a new list item at NewIndex
            const FeatStd::String *newItem = request.GetItem<FeatStd::String>();
            requiresUpdate = newItem != 0 && mSettingsMenu.InsertAt(request.NewIndex(), *newItem);
            break;
        }

        case ListRequestType::ModifyItem: {
            // existing list item gets modified at index NewIndex
            const FeatStd::String *newItem = request.GetItem<FeatStd::String>();
            if (newItem != 0 && request.NewIndex() < mSettingsMenu.Count()) {
                mSettingsMenu[request.NewIndex()] = *newItem;
                listChanged = true;
            }
            break;
        }

        case ListRequestType::ClearList:
            // clear the list
            mSettingsMenu.Clear();
            listChanged = true;
            break;

        case ListRequestType::MoveItem:
            // move a list item to a new index
            listChanged =  mSettingsMenu.Move(request.NewIndex(), request.OldIndex());
            break;

        case ListRequestType::RemoveItem:
            // remove a list item
            listChanged = mSettingsMenu.RemoveAt(request.NewIndex());
            break;

        case ListRequestType::NewFragment:
            // explicit request for a new list fragment
            requiresUpdate = true;
            break;

        case ListRequestType::PrefetchItems:
            // nothing to do here - the list is not prefetching
            // this request causes normally the model to read data from external
            // data sources. it prepares near future NewFragment requests. for example
            // a list widget might send prefetch request for next list pages when the user
            // scrolls down.
            // No events are sent back to the view component in response to the prefetch
            // request.
            break;

        case ListRequestType::None:
        default:
            COURIER_DEBUG_FAIL();
            break;
    }

    if (listChanged) {
        // if the list got modified, increase data revision number
        (void) BindingSourceRevisionStore::IncRevision(ItemKey::SettingsMenuItem);
    }

    // return true if the request requires updates to be sent
    return requiresUpdate || listChanged;
}

```

<div class="contents" id="bkmrk-the-helper-class-cha"><div class="textblock"><div class="fragment">  
</div><dl class="note"><dt></dt><dd><p class="callout info">The helper class ChangeTracker is implemented in SampleApplication and is not part of [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) framework.</p>

</dd></dl></div></div>####   
**Frequently Asked Questions** 

##### <a class="anchor" id="bkmrk--41"></a>I get unresolved externals for symbols Courier::DataBindingPrivate::gInfrastructure

DataBinding requires certain application specific infrastructure for operation (e.g. description of your data model). Normally this infrastructure will be generated by CourierGenerator during XCDDL generation. If the application does not use a generated data model, the infrastructure is missing and will cause the listed unresolved external.

To resolve the link error add the macro COURIER\_DATABINDING\_DEFAULT\_INFRASTRUCTURE to the top level scope of one of the applications source (not header!) file.

```
// no generated data items in this build -> define default infrastructure
#include <Courier/Courier.h>
COURIER_DATABINDING_DEFAULT_INFRASTRUCTURE();

```

---

##### <a class="anchor" id="bkmrk--42"></a>My list widget invokes RequestPrefetch on a bindable list property but the request never gets to the model component

---

If your list is not updated in fragments (windowSize is defined in XCDDL), requesting to prefetch the list makes no sense (you already receive the complete list in a [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html)) and therefore the request is ignored.

##### <a class="anchor" id="bkmrk--43"></a>My widget changes a bound property value but the change is not propageted back to the model

Most likely you forgot to inform data binding about the change with FrameworkWidget::PropertyModified.

```
void SampleWidget::SetEnabled(bool val)
{
    if ((mEnabled && !val) || (!mEnabled && val)) {
        mEnabled = val;
        if (GetNode() != 0) {
            GetNode()->SetRenderingEnabled(mEnabled);
        }
        PropertyModified("Enabled");
    }
}
```

---

##### <a class="anchor" id="bkmrk--45"></a>I get a compile error in BindableProperty.h (use of undefined type Courier::Diagnostics::Private::CtaOnlyTrue)

Most likely you defined a bindable property with a pointer or reference. As the ownership to referred data is not correctly managed, data binding does not support pointer, C/C++ arrays, and references as property type. Check [Reference Types](#bkmrk-reference-types%C2%A0) how to handle buffer data.

```
    typedef const Char* ConstCharPtr;
    const ConstCharPtr GetLabelX() const {
        return 0;
    }

    void SetLabelX(ConstCharPtr) {
    };
    ...

    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___widget_base.html#ga5fbdec0aa0a5d67f941ad5e4bef470da">CdaWidgetDef</a>(SampleWidget, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___m_e_s_s_a_g_i_n_g.html#ggac4e3f0853af916ef773e65d02a15c95dac1224e2f0bf57d4eede7026521a13aa8">Widget</a>)
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#ga898c10e4eb9c1b99355e984e1de3be24">CdaBindableProperty</a>(LabelX, ConstCharPtr, GetLabelX, SetLabelX)     // njet - will cause compile time assertion
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___d_a_t_a_b_i_n_d_i_n_g.html#gadfe0cb4e5e7e411e29c60e3061371996">CdaBindablePropertyEnd</a>()
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___widget_base.html#ga5b5647ca32644fc63627059a7f7fdef8">CdaWidgetDefEnd</a>()
```

---

##### <a class="anchor" id="bkmrk--47"></a>My widget properties gets updates disregarding the data did change or not

Data binding does not check if the widget property data changed prior to updating the property. This is in control of the model component which can set the modified flags in the [Courier::DataItemMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_data_item_msg.html) accordingly. If the model fails to do this correctly, it is a good practice to check in the setter of the property if the new property value differs from the existing. If the values did not change, the widget should ignore the setter invocation.

```
void SampleWidget::SetEnabled(bool val)
{
    if ((mEnabled && !val) || (!mEnabled && val)) {
        mEnabled = val;
        if (GetNode() != 0) {
            GetNode()->SetRenderingEnabled(mEnabled);
        }
        PropertyModified("Enabled");
    }
}
```

---

##### <a class="anchor" id="bkmrk--49"></a>My attempts to establish a binding between a data item and widget property fails

Reasons of failure

<div class="contents" id="bkmrk-the-data-types-of-wi"><div class="contents"><div class="textblock">- The data types of widget property and data item don't match and type conversion is disabled or according [Courier::TypeConverter](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_type_converter.html) objects could not be found.
- The binding requires type conversion and the type exceeds COURIER\_TYPE\_CONVERSION\_BUFFER\_SIZE.
- The data item is not an elementary item
- Typo in widget type or property type name

</div></div></div>If data types don't match, enabling standard type converts may help ([Courier::RegisterStdTypeConverters](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html#a7be6d0e4325230b79f6dbae25125e059)). They supply conversion functions between built-in numerical types.