You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ListView: when adding/removing items, app immediately crashes on Windows, raise 'ItemTemplate count has exceeded the limit of 23' Exception on Android
#41
Open
heldap opened this issue
Jul 19, 2023
· 2 comments
namespace DebugView
open Fabulous
open Fabulous.Maui
open type Fabulous.Maui.View
module App =
let mutable id = 0
type Item =
{
Name: string
Detail: string
}
static member create () =
let i = {Name= $"Dummy{id}"; Detail="Dummy Dum"}
id <- id + 1
i
type Model = { Items: Item list }
type Msg =
| Add
| RemoveLast
let init () = { Items = [Item.create()] }, Cmd.none
let removeLast =
function
| [] -> []
| l -> List.removeAt (l.Length-1) l
let update msg model =
match msg with
| Add -> {model with Items = List.append model.Items [Item.create()]}, Cmd.none
| RemoveLast -> {model with Items = removeLast model.Items}, Cmd.none
let view model =
Application(
ContentPage(
(VStack(){
ListView model.Items (fun i -> TextCell(i.Name).detailText(i.Detail))
HStack(){
Button("Add", Add)
Button("Remove Last", RemoveLast)
}
})
)
)
let program = Program.statefulWithCmd init update view
On Windows Machine target, whether I click Add or Remove, the app crash: it seems that any attempt to modify ListView's items results in a crash (Win32 exception)
Here is the log:
Debug: Unhandled exception: System.ArgumentException: Value is an invalid value for ItemTemplate (Parameter 'value')
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
at [email protected](FSharpValueOption`1 _arg1, FSharpValueOption`1 newValueOpt, IViewNode node)
at Fabulous.ScalarAttributeDefinitions.CreateAttributeData@73-1.Invoke(FSharpValueOption`1 oldValueOpt, FSharpValueOption`1 newValueOpt, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](a _arg1, WidgetCollectionItemChanges diffs, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](WidgetDiff diff, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](WidgetDiff diff, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at Fabulous.Reconciler.update(FSharpFunc`2 canReuseView, FSharpValueOption`1 prevOpt, Widget next, IViewNode node)
at [email protected](Unit unitVar0)
Debug: Unhandled exception: System.ArgumentException: Value is an invalid value for ItemTemplate (Parameter 'value')
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
at [email protected](FSharpValueOption`1 _arg1, FSharpValueOption`1 newValueOpt, IViewNode node)
at Fabulous.ScalarAttributeDefinitions.CreateAttributeData@73-1.Invoke(FSharpValueOption`1 oldValueOpt, FSharpValueOption`1 newValueOpt, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](a _arg1, WidgetCollectionItemChanges diffs, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](WidgetDiff diff, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](WidgetDiff diff, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at Fabulous.Reconciler.update(FSharpFunc`2 canReuseView, FSharpValueOption`1 prevOpt, Widget next, IViewNode node)
at [email protected](Unit unitVar0)
at [email protected]()
at Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(Action action)
at [email protected](FSharpFunc`2 arg00)
at Fabulous.ViewAdapters.ViewAdapter`3.OnStateChanged(StateChangedEventArgs args)
'DebugView.exe' (CoreCLR: clrhost): Loaded 'D:\Projects\_Apps\DebugView\DebugView\bin\Debug\net7.0-windows10.0.19041.0\win10-x64\AppX\System.IO.Compression.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Debug: Unhandled exception: System.ArgumentException: Value is an invalid value for ItemTemplate (Parameter 'value')
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
at [email protected](FSharpValueOption`1 _arg1, FSharpValueOption`1 newValueOpt, IViewNode node)
at Fabulous.ScalarAttributeDefinitions.CreateAttributeData@73-1.Invoke(FSharpValueOption`1 oldValueOpt, FSharpValueOption`1 newValueOpt, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](a _arg1, WidgetCollectionItemChanges diffs, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](WidgetDiff diff, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at [email protected](WidgetDiff diff, IViewNode node)
at Fabulous.ViewNode.Fabulous.IViewNode.ApplyDiff(WidgetDiff& diff)
at Fabulous.Reconciler.update(FSharpFunc`2 canReuseView, FSharpValueOption`1 prevOpt, Widget next, IViewNode node)
at [email protected](Unit unitVar0)
at [email protected]()
at Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(Action action)
at [email protected](FSharpFunc`2 arg00)
at Fabulous.ViewAdapters.ViewAdapter`3.OnStateChanged(StateChangedEventArgs args)
at [email protected](StateChangedEventArgs arg00)
at Microsoft.FSharp.Control.CommonExtensions.SubscribeToObservable@2281.System.IObserver<'T>.OnNext(T args) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 2283
at Microsoft.FSharp.Control.FSharpEvent`1.Trigger(T arg) in D:\a\_work\1\s\src\FSharp.Core\event.fs:line 175
at Fabulous.Runners.Runner`4.dispatch(msg msg)
The program '[11072] DebugView.exe' has exited with code 3221226107 (0xc000027b).
On Android, with both emulator (Android 10.0, API 29) and my phone (Android 6.0 API 23);
after a while adding and removing items, I get a System.Exception:'ItemTemplate count has exceeded the limit of 23 Please make sure to reuse DataTemplate objects
The text was updated successfully, but these errors were encountered:
heldap
changed the title
ListView crashes when adding/removing items, immediately crashes on Windows, provoke ItemTemplate count has exceeded the limit of 23 on Android
ListView: when adding/removing items, app immediately crashes on Windows, raise 'ItemTemplate count has exceeded the limit of 23' Exception on Android
Jul 19, 2023
Thanks for the report!
I managed to reproduce with the example given 👍
What's happening in your case is that Fabulous expects your items to be a stable reference value (aka mutable list) instead of a non-mutable one (like F# list type where a new list instance is created with each mutation).
If the reference changes, Fabulous will consider the whole list needs to be reloaded and will lose the DataTemplates that were created previously -- causing the crash on Android after reaching the limit of .NET MAUI.
A workaround would be to change the Model type:
typeModel={ Items:ObservableCollection<Item>}
Note: I'm using ObservableCollection instead of any System.Collections.IList type, because .NET MAUI expects the collection to raise events when adding/removing items which ObservableCollection do
Then, you can still add and remove items like usual.
This approach will work, though it has some drawbacks because of the mutated collection (especially if you want clean separation between states).
Virtualized collection widgets like ListView are very tricky to work with in Fabulous, and can easily crash.
I'm not really satisfied with our implementation.
Thanks you for the quick reply :)
This workaround is fine for my needs.
May I close this issue ?
It could be interesting to keep it opened though, as someone else might encounter this issue (since using F# list is instinctive): keeping it opened makes the workaround visible.
Code:
On Windows Machine target, whether I click Add or Remove, the app crash: it seems that any attempt to modify ListView's items results in a crash (Win32 exception)
Here is the log:
On Android, with both emulator (Android 10.0, API 29) and my phone (Android 6.0 API 23);
after a while adding and removing items, I get a System.Exception:'ItemTemplate count has exceeded the limit of 23 Please make sure to reuse DataTemplate objects
The text was updated successfully, but these errors were encountered: