Closed Code-DJ closed 9 months ago
Hi the ListView issue works now but there seems to be something else that isn't right. Let me know if I should create a new issue.
I get the following error on 2.0.8-beta (works fine on 2.0.5-beta) - see code below:
Operation is not valid due to the current state of the object.
at at MauiReactor.Internals.Validate.EnsureNotNull[Label](Label value)
at at MauiReactor.VisualNode`1[[Microsoft.Maui.Controls.Label, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnAnimate()
at at MauiReactor.VisualElement`1[[Microsoft.Maui.Controls.Label, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnAnimate()
at at MauiReactor.View`1[[Microsoft.Maui.Controls.Label, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnAnimate()
at at MauiReactor.Label`1[[Microsoft.Maui.Controls.Label, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnAnimate()
at at MauiReactor.VisualNode.Animate()
I have a variation of your MudEntry. Run the following with .UseMauiReactorApp<ListViewPage>()
:
In the simulator make sure you have Connect Hardware Keyboard so you can type fast. As soon as you open the Modal dialog, click in the Editor and start typing fast. The app crashes. If you wait, type one character, wait - then start typing fast, it works.
public class StartPage : Component
{
public override VisualNode Render() => new NavigationPage()
{
new ContentPage()
{
new Button("Open Child Page")
.OnClicked(async () => await Navigation!.PushModalAsync<ChildPage>())
}
};
}
public class ChildPageState
{
public string? SearchText { get; set; }
}
public class ChildPage : Component<ChildPageState>
{
public override VisualNode Render() => new NavigationPage()
{
new ContentPage
{
new Grid
{
new MudEditor()
.Label("Test")
}
}
.Title("Child Page")
.BackgroundColor(Colors.Aquamarine)
}
.OniOS(page => page.Set(MauiControls.PlatformConfiguration.iOSSpecific.Page.ModalPresentationStyleProperty, MauiControls.PlatformConfiguration.iOSSpecific.UIModalPresentationStyle.FormSheet));
}
class MudEditorState
{
public string? Text { get; set; }
public bool Focused { get; set; }
public bool IsEmpty { get; set; } = true;
public bool Invalidate { get; set; }
}
class MudEditor : Component<MudEditorState>
{
private MauiControls.Editor? _editorRef;
private Action<string>? _textChangedAction;
private string? _label;
public MudEditor OnTextChanged(Action<string> textChangedAction)
{
_textChangedAction = textChangedAction;
return this;
}
public MudEditor Label(string label)
{
_label = label;
return this;
}
public override VisualNode Render()
{
return new Grid("Auto", "*")
{
new Editor(editorRef => _editorRef = editorRef)
.Text(State.Text ?? "")
// .OnAfterTextChanged(OnTextChanged)
.OnTextChanged((s, e) =>
{
SetState(state => state.Invalidate = (State.Text?.Length == 0 && e.NewTextValue.Length > 0) || (State.Text?.Length > 0 && e.NewTextValue.Length == 0));
SetState(state => state.Text = e.NewTextValue, State.Invalidate);
_textChangedAction?.Invoke(e.NewTextValue);
})
.HFill()
.VFill()
.OnFocused(() => SetState(s => s.Focused = true))
.OnUnfocused(() => SetState(s => s.Focused = false)),
new Label(_label)
.OnTapped(() => _editorRef?.Focus())
.Margin(5,0)
.HStart()
.VCenter()
.TranslationY(State.Focused || !State.IsEmpty ? -20 : 0)
.ScaleX(State.Focused || !State.IsEmpty ? 0.8 : 1.0)
.AnchorX(0)
.TextColor(!State.Focused || State.IsEmpty ? Colors.Gray : Colors.Red)
.WithAnimation(duration: 200),
}
.HFill()
.VFill();
}
}
side note: not sure why the entire editor is sliding out of view when hardware keyboard is connected. It looks like a MAUI thing though.
Hi, looking at the issue right now, I'm sorry for the problems caused, I'm trying to make it work with both patterns but it seems more complicated than I thought initially. Your help is much appreciated!
out of curiosity do you see (or have measured) any performance gains in adopting the new format for your list views?
Hi @adospace I have mostly done testing on iOS simulators and haven't seen a difference. I think it will be apparent on older devices. Also, I had to revert it with 2.0.8 because for Flyout Page, the pages (master and detail) were not displaying correctly (it was like the page was getting displayed in 100x100 area instead of taking the entire space. Thanks!
Hi, thanks, latest version 2.0.9 contains a new component called FrameRateIndicator: put it anywhere on top of other controls and it will show the realtime FPS.
You need to enable it for the application:
var builder = MauiApp.CreateBuilder();
builder
.UseMauiReactorApp<HomePage>(app =>
{
app.AddResource("Resources/Styles/DefaultTheme.xaml");
app.SetWindowsSpecificAssetsDirectory("Assets");
})
#if DEBUG
.EnableMauiReactorHotReload()
//This will enable the FrameRateIndicator widget
//Disable before publishing the app
.EnableFrameRateIndicator()
#endif
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
})
.UseMauiCommunityToolkit();
builder.Services.AddSingleton<Services.IncrementService>();
return builder.Build();
public override VisualNode Render()
=> ContentPage([
Grid("*", "*", [
new ListView(MauiControls.ListViewCachingStrategy.RecycleElementAndDataTemplate)
.HasUnevenRows(true)
.ItemsSource(_allMonkeys, RenderMonkeyTemplate),
new Internals.FrameRateIndicator()
.VStart()
.HEnd()
.BackgroundColor(Colors.White)
]),
]);
just in case you want to measure page performance drops
@adospace another reason I reverted was because it sounded like the new format was an experiment (as in it may go away). If this is the new way, I will use the new way and report any issues. Thanks!
The new way is an experiment in the sense that until I don't feel it's secure enough for production I won't publish version 2 as stable. The new and classic way to declare components will be part of the stable version 2 and both will be kept in the future as I guess any developer has different preferences (for example, those coming from Flutter should like the new way).
Said that anyone can use one or the other or both in the same app/component. The new way has some pros and cons, in particular, it should have low memory pressure spending a bit more on CPU cycles, but again as you pointed out it could be visible only to lower-end devices or on really complex pages.
ListView works fine when you have a single ItemTemplate but for multiple ItemTemplates it renders the wrong cached rows.
Run the following with
.UseMauiReactorApp<ListViewPage>()
: