Summary
Add a generic ListView<T> that extends ListView and implements IValue<T>, so the selected item is exposed as the actual object of type T rather than as an integer index.
Also add an AspectGetter (Func<T,string>?) delegate to ListWrapper<T> and ListView<T> so developers can control how items are converted to display text without writing a custom IListDataSource.
Motivation
The existing ListView exposes selection as int? Value / int? SelectedItem (an index). When the underlying data is a typed collection, callers must keep the collection and the list in sync manually and cast back to get the selected object. A generic ListView<T> eliminates that friction:
`csharp
// Before
listView.SelectedItem = 2;
MyObject selected = myCollection[listView.SelectedItem!.Value];
// After
ListView listView = new ();
listView.SetSource(myCollection);
MyObject? selected = listView.Value;
`
Similarly, ListWrapper<T> currently calls ToString() unconditionally. For domain objects, ToString() is rarely suitable for display, forcing developers to implement a full custom IListDataSource just to change one string:
csharp // Before: full custom IListDataSource required // After listView.AspectGetter = obj => obj.Name;
Proposed API
ListView<T> : ListView, IValue<T>
| Member |
Type |
Notes |
Value |
new T? |
Primary — the selected object |
SelectedItem |
new T? |
Convenience alias for Value |
Index |
int? (get/set) |
Access the underlying int? index |
AspectGetter |
Func<T,string>? |
Custom display-text converter |
SetSource(ObservableCollection<T>?) |
method |
Typed source |
ValueChanging |
event EventHandler<ValueChangingEventArgs<T?>> |
Typed, cancellable |
ValueChanged |
event EventHandler<ValueChangedEventArgs<T?>> |
Typed |
ListWrapper<T>.AspectGetter
csharp public Func<T, string>? AspectGetter { get; set; }
When set, used in Render() and GetMaxLengthItem() instead of ToString(). Fully backward-compatible (null by default).
Additional context
SelectedItem mirrors the existing ListView doc: "a convenience property that is an alias for Value"
Index is the way to get/set the int? index when using ListView<T>
- A UICatalog scenario demonstrating all features would be included
- No breaking changes to
ListView or ListWrapper<T>
Summary
Add a generic
ListView<T>that extendsListViewand implementsIValue<T>, so the selected item is exposed as the actual object of typeTrather than as an integer index.Also add an
AspectGetter(Func<T,string>?) delegate toListWrapper<T>andListView<T>so developers can control how items are converted to display text without writing a customIListDataSource.Motivation
The existing
ListViewexposes selection asint? Value/int? SelectedItem(an index). When the underlying data is a typed collection, callers must keep the collection and the list in sync manually and cast back to get the selected object. A genericListView<T>eliminates that friction:`csharp
// Before
listView.SelectedItem = 2;
MyObject selected = myCollection[listView.SelectedItem!.Value];
// After
ListView listView = new ();
listView.SetSource(myCollection);
MyObject? selected = listView.Value;
`
Similarly,
ListWrapper<T>currently callsToString()unconditionally. For domain objects,ToString()is rarely suitable for display, forcing developers to implement a full customIListDataSourcejust to change one string:csharp // Before: full custom IListDataSource required // After listView.AspectGetter = obj => obj.Name;Proposed API
ListView<T> : ListView, IValue<T>Valuenew T?SelectedItemnew T?ValueIndexint?(get/set)AspectGetterFunc<T,string>?SetSource(ObservableCollection<T>?)ValueChangingevent EventHandler<ValueChangingEventArgs<T?>>ValueChangedevent EventHandler<ValueChangedEventArgs<T?>>ListWrapper<T>.AspectGettercsharp public Func<T, string>? AspectGetter { get; set; }When set, used in
Render()andGetMaxLengthItem()instead ofToString(). Fully backward-compatible (nullby default).Additional context
SelectedItemmirrors the existingListViewdoc: "a convenience property that is an alias for Value"Indexis the way to get/set the int? index when usingListView<T>ListVieworListWrapper<T>