adospace / reactorui-maui

MauiReactor is a MVU UI framework built on top of .NET MAUI
MIT License
586 stars 49 forks source link

MauiReactor Stacklayout inside datatemplate #86

Closed MattePozzy closed 1 year ago

MattePozzy commented 1 year ago

Hi, I'm using some 3rd part component that have a property called ContentTemplate that accepts a DataTemplate.

I have used this code but it goes on error:

class MainPage : Component
    {
        SfPopup poppy;
        public override VisualNode Render()
        {
            poppy = new SfPopup()
            {
                IsOpen = false,
                ContentTemplate = new MauiControls.DataTemplate(() =>
                {
                    StackLayout stack = new()
                    {
                        new Label("testo popup")
                    };

                    return stack;
                })
            };

            return new ContentPage("Pagina uno")
            {
                new ScrollView() {
                    new Label("Main page"),
                    new Button().Text("Apri popup").OnClicked(ApriPopup)
                }.VCenter().HCenter()
            };
        }

        private void ApriPopup()
        {
            poppy.Show();
        }
    }

This is the erorr: image

How can i use the MauiReactor Stacklayout inside a DataTemplate?

Thank you.

adospace commented 1 year ago

Probably you have to augment the a bit more the wrapper to properly handle the SfPopup native control. can you show the code where you wrap SfPopup? like

[Scaffold(typeof(...SfPopup))]
public partial class SfPopup {}
MattePozzy commented 1 year ago

Ok, now I have created this one:

    [Scaffold(typeof(Syncfusion.Maui.Popup.SfPopup))]
    partial class MioPopUp { }

but when compile gives me this errors: image

so I have added this one:

    [Scaffold(typeof(Syncfusion.Maui.Core.SfView), true)]
    partial class MiaView { }

and now the error is this one: image

adospace commented 1 year ago

ok, I see that SfPopup doesn't provide a direct way to set the content so you have to use a TemplateHost (that is a class that allows you to create a native Maui control from a MauiReactor VisualNode):

[Scaffold(typeof(Syncfusion.Maui.Popup.SfPopup))]
public partial class SfPopup 
{
    public SfPopup Content(Func<VisualNode> render)
    {
        this.Set(Syncfusion.Maui.Popup.SfPopup.ContentTemplateProperty, 
            new MauiControls.DataTemplate(() => TemplateHost.Create(render()).NativeElement));

        return this;
    }
}

[Scaffold(typeof(Syncfusion.Maui.Core.SfView))]
public abstract class SfView { }

class MainPageState
{
    public bool IsPopupOpen { get; set; }
}

class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage("Pagina uno")
        {
            new VStack() {
                new Label("Main page"),
                new Button().Text("Apri popup").OnClicked(ApriPopup),

                new SfPopup()
                    .Content(()=>
                        new VStack()
                        {
                            new Label("my label")
                        })
                    .IsOpen(State.IsPopupOpen)
                    .OnClosed(()=>SetState(s => s.IsPopupOpen = false, false))

            }.VCenter().HCenter()
        };
    }

    private void ApriPopup()
    {
        SetState(s => s.IsPopupOpen = true);
    }
}
MattePozzy commented 1 year ago

ok, I see that SfPopup doesn't provide a direct way to set the content so you have to use a TemplateHost (that is a class that allows you to create a native Maui control from a MauiReactor VisualNode):

[Scaffold(typeof(Syncfusion.Maui.Popup.SfPopup))]
public partial class SfPopup 
{
    public SfPopup Content(Func<VisualNode> render)
    {
        this.Set(Syncfusion.Maui.Popup.SfPopup.ContentTemplateProperty, 
            new MauiControls.DataTemplate(() => TemplateHost.Create(render()).NativeElement));

        return this;
    }
}

[Scaffold(typeof(Syncfusion.Maui.Core.SfView))]
public abstract class SfView { }

class MainPageState
{
    public bool IsPopupOpen { get; set; }
}

class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage("Pagina uno")
        {
            new VStack() {
                new Label("Main page"),
                new Button().Text("Apri popup").OnClicked(ApriPopup),

                new SfPopup()
                    .Content(()=>
                        new VStack()
                        {
                            new Label("my label")
                        })
                    .IsOpen(State.IsPopupOpen)
                    .OnClosed(()=>SetState(s => s.IsPopupOpen = false, false))

            }.VCenter().HCenter()
        };
    }

    private void ApriPopup()
    {
        SetState(s => s.IsPopupOpen = true);
    }
}

Thank you! It works great!

juanyacovino77 commented 1 year ago

ok, I see that SfPopup doesn't provide a direct way to set the content so you have to use a TemplateHost (that is a class that allows you to create a native Maui control from a MauiReactor VisualNode):

[Scaffold(typeof(Syncfusion.Maui.Popup.SfPopup))]
public partial class SfPopup 
{
    public SfPopup Content(Func<VisualNode> render)
    {
        this.Set(Syncfusion.Maui.Popup.SfPopup.ContentTemplateProperty, 
            new MauiControls.DataTemplate(() => TemplateHost.Create(render()).NativeElement));

        return this;
    }
}

[Scaffold(typeof(Syncfusion.Maui.Core.SfView))]
public abstract class SfView { }

class MainPageState
{
    public bool IsPopupOpen { get; set; }
}

class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage("Pagina uno")
        {
            new VStack() {
                new Label("Main page"),
                new Button().Text("Apri popup").OnClicked(ApriPopup),

                new SfPopup()
                    .Content(()=>
                        new VStack()
                        {
                            new Label("my label")
                        })
                    .IsOpen(State.IsPopupOpen)
                    .OnClosed(()=>SetState(s => s.IsPopupOpen = false, false))

            }.VCenter().HCenter()
        };
    }

    private void ApriPopup()
    {
        SetState(s => s.IsPopupOpen = true);
    }
}

hey

This code only works for me by adding: builder.ConfigureSyncfusionCore(); at MauiProgram.cs

if not, and exception "Handler not found for Syncfusion.Maui.Popup.SfPopup" was raised

Its that ok? Docs dont mentioned nothing about this..

MattePozzy commented 1 year ago

ok, I see that SfPopup doesn't provide a direct way to set the content so you have to use a TemplateHost (that is a class that allows you to create a native Maui control from a MauiReactor VisualNode):

[Scaffold(typeof(Syncfusion.Maui.Popup.SfPopup))]
public partial class SfPopup 
{
    public SfPopup Content(Func<VisualNode> render)
    {
        this.Set(Syncfusion.Maui.Popup.SfPopup.ContentTemplateProperty, 
            new MauiControls.DataTemplate(() => TemplateHost.Create(render()).NativeElement));

        return this;
    }
}

[Scaffold(typeof(Syncfusion.Maui.Core.SfView))]
public abstract class SfView { }

class MainPageState
{
    public bool IsPopupOpen { get; set; }
}

class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage("Pagina uno")
        {
            new VStack() {
                new Label("Main page"),
                new Button().Text("Apri popup").OnClicked(ApriPopup),

                new SfPopup()
                    .Content(()=>
                        new VStack()
                        {
                            new Label("my label")
                        })
                    .IsOpen(State.IsPopupOpen)
                    .OnClosed(()=>SetState(s => s.IsPopupOpen = false, false))

            }.VCenter().HCenter()
        };
    }

    private void ApriPopup()
    {
        SetState(s => s.IsPopupOpen = true);
    }
}

hey

This code only works for me by adding: builder.ConfigureSyncfusionCore(); at MauiProgram.cs

if not, and exception "Handler not found for Syncfusion.Maui.Popup.SfPopup" was raised

Its that ok? Docs dont mentioned nothing about this..

Hi, yes is correct.

Check the syncfusion documentation to know more: https://help.syncfusion.com/maui/popup/getting-started

There is a a sample where the app is configured and the code builder.ConfigureSyncfusionCore();is used ;)

juanyacovino77 commented 1 year ago

So, for every 3rd party control we should write smothing like this? This should be on ReactorMaui docs. thanks

adospace commented 1 year ago

It's not a MauiReactor thing, every vendor generally uses a custom extension method of the app builder to register its handlers. Please refer to the vendors documentation to see how to initialize their library.

juanyacovino77 commented 1 year ago

It's not a MauiReactor thing, every vendor generally uses a custom extension method of the app builder to register its handlers. Please refer to the vendors documentation to see how to initialize their library.

I understand, it would be nice to advise that info at ReactorMaui doc "3rd party wrapper" thanks