BindableList
A basic way to make a Bindable list is just to throw a regular C# List into a Bindable:
public Bindable<List<int>> IntList = new(new());
This will work fine, but has some limations. For example, editing the list does not trigger change events, so you'll need to raise them yourself:
IntList.Value[3] = 5; // Does not trigger OnChange!
IntList.NotifyChanged(); // Manually trigger OnChange
Additionally, there's no way to detect whether a single element changed, or if the whole list changed. To get those features, use the BindableList class.
Instead, use BindableList:
public BindableList<int> IntList = new();
This class inherits from Bindable<List<int>> and also implements IList<T> which allows you to perform standard list operations:
// Iterate over the list:
foreach (var item in IntList) { ... }
// Add an item - triggers OnElementAdd
IntList.Add(5);
// Edit an item - triggers OnElementChange
IntList[0] = 6;
// Remove an item - triggers OnElementRemove
IntList.Remove(0);
// Sorts the list - triggers OnChange
IntList.Sort();
Events
In addition to OnChange and OnChangeWithValue, BindableList provides the following events:
OnElementAdd: Invoked whenAdd,AddRange,Insert, orInsertRangeare called.OnElementChange: Invoked whenlist[index] = valueOnElementMoved: Invoked whenMoveis called.OnElementSwap: Invoked whenSwapis called.OnElementRemove: Invoked whenRemoveorRemoveRangeis called.OnChange: Invoked when the underlying listValueis changed, or whenClear,Sort, orReverseare called.
DerivedList
You can standard Linq operations with BindableList, but they will generate a regular IEnumerable, not a Bindable.
To cover this gap, we added the methods DeriveSelect, DeriveConcat, DeriveCast, and DeriveDictionary. These will each return a Bindable which is bound to the original list. For example:
var list = new BindableList<int>();
var derivedList = list.DeriveSelect(n => n + 1);
list.Add(5);
list.Add(7);
// derivedList will now have [6, 8].
You can also use Derived.From to select from one list or the other, and all the change events will carry over to the appropriate list. When the list switches, OnChange will be invoked.
var list1 = new BindableList<int>() { 1, 2 };
var list2 = new BindableList<int>() { 3, 4 };
var selector = new Bindable<bool>();
var selectedList = Derived.From(selector, list1, list2, (sel, l1, l2) => sel ? l1 : l2);
this.Bind(selectedList, Debug.Log(string.Join(", ", selectedList)));
// This prints "1, 2" because selectedList == list1
selector.Value = true;
// This prints "3, 4" because selectedList == list2