---
title: Publish collection-mutation notification
summary: Raises collection change notifications after insert, clear, remove, and set operations complete.
status: draft
owner: SAIF Team
last_reviewed: 2026-07-30
library: SAIF.Framework.Bindable
reference_type: package
operation_id: OP-BIND-002
trigger: CollectionBase completion hook on a clsBindableCollectionBase subclass
---

# Publish collection-mutation notification

This operation converts the four `CollectionBase` lifecycle callbacks — insert, clear, remove, and set completion — into a single, uniform `ListChanged` notification for subscribers of a `clsBindableCollectionBase` instance. It exists so that a data-bound list control can react to any collection edit through one event rather than four.

| Field | Value |
| --- | --- |
| **Operation ID** | `OP-BIND-002` |
| **Trigger** | `CollectionBase` invokes `OnInsertComplete`, `OnClearComplete`, `OnRemoveComplete`, or `OnSetComplete` on the subclass after the underlying list mutation finishes. |
| **Inputs** | Mutation type plus the affected index/value, both supplied by the `CollectionBase` lifecycle hook. |
| **Outputs** | `ListChanged(this, e)` when a subscriber is attached; otherwise no side effect. |
| **Primary components** | `clsBindableCollectionBase.OnInsertComplete`, `clsBindableCollectionBase.OnClearComplete`, `clsBindableCollectionBase.OnRemoveComplete`, `clsBindableCollectionBase.OnSetComplete`, `clsBindableCollectionBase.OnListChanged` |
| **Entry point** | `SAIF.Framework.Bindable\clsBindableCollectionBase.cs` |

## Steps

1. `CollectionBase` calls the completion hook that matches the mutation that just finished — the operation never starts on its own; it is always a reaction to a prior insert, clear, remove, or set.
2. The hook maps itself to the corresponding `ListChangedType` value:
   - `OnInsertComplete` maps to `ListChangedType.ItemAdded`.
   - `OnClearComplete` maps to `ListChangedType.Reset`.
   - `OnRemoveComplete` maps to `ListChangedType.ItemDeleted`.
   - `OnSetComplete` maps to `ListChangedType.ItemChanged`.
3. The hook constructs a `ListChangedEventArgs` instance carrying the mapped change type and the affected index.
   - For `OnClearComplete`, the index is always `0`, since a full reset has no single affected position.
4. The hook passes the constructed event arguments to `OnListChanged(...)`.
5. `OnListChanged(...)` checks whether the `ListChanged` event delegate has at least one subscriber.
6. If a subscriber is attached, it invokes `ListChanged(this, e)`.
7. If no subscriber is attached, it returns without raising an event and without throwing.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Collection mutation completes]) --> Hook[Enter matching completion hook]
	Hook --> Map[Map hook to ListChangedType]
	Map --> Args[Create ListChangedEventArgs]
	Args --> Check{ListChanged subscriber attached?}
	Check -->|Yes| Raise[Invoke ListChanged(this, e)]
	Check -->|No| NoOp([Return without side effects])
	Raise --> EndOk([Notification delivered])
```

## Failure and edge-case behavior

- No subscriber attached: `OnListChanged(...)` exits quietly because it guards the delegate invocation with a null check, the same defensive pattern used in [Notify modified-state change](modified-state-change-notification.md).
- Clear/reset operation: because a reset affects the whole collection rather than one position, the notification always reports index `0` regardless of how many items were removed.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `SAIF.Framework.Bindable\clsBindableCollectionBase.cs`
