adospace / reactorui-maui

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

State change not for all components #149

Closed MattePozzy closed 10 months ago

MattePozzy commented 10 months ago

Hi, I have some custom components that I canno't update trough update the State value.

ezgif com-video-to-gif (2)

I think that all the componets was created in the same way (see Valore properties), so I can't understand because some works and other doesn't.

The Maui Label works fine.

Here a repo.

What I have done wrong? How can I fix this?

Thank you!

adospace commented 10 months ago

Hi,

This class https://github.com/Raystorm7/StateChangeIssue/blob/main/Project1/VolosPicker.cs is not working as it's written: you're deriving from a MauiReactor component like Grid, then internally you're using the TemplateHost which is a really special class that should be used only in scaffolding DataTemplates or in unit tests and I'm not sure can work in the way you're using it.

I'm not sure what you're trying to achieve but I can suggest following the MauiReactor guidelines (https://adospace.gitbook.io/mauireactor/) to build comparable applications (in general avoid deriving from components but compose your UI in the Render method).

For the above reason, I can't guarantee that the MauiReactor rendering flow could work in your case.

MattePozzy commented 10 months ago

Hi,

This class https://github.com/Raystorm7/StateChangeIssue/blob/main/Project1/VolosPicker.cs is not working as it's written: you're deriving from a MauiReactor component like Grid, then internally you're using the TemplateHost which is a really special class that should be used only in scaffolding DataTemplates or in unit tests and I'm not sure can work in the way you're using it.

I'm not sure what you're trying to achieve but I can suggest following the MauiReactor guidelines (https://adospace.gitbook.io/mauireactor/) to build comparable applications (in general avoid deriving from components but compose your UI in the Render method).

For the above reason, I can't guarantee that the MauiReactor rendering flow could work in your case.

Hi, thank you for the reply but the method which use TemplateHost is not used anymore inside the class.

I'm trying to create a reusable custom component. It's derived from a Grid because it is made up of multiple objects, so I need to add these object to the container that is a Grid.

Also because the components VolosEntry that derives from SfTextInputLayout works fine.

Could you help me?

adospace commented 10 months ago

if you need something inside a grid why not just create a grid in the render method: pseudo code:

class VolosPicker : Component
{

public override VisualNode Render()
{
  return new Grid()
  {
    .....
  }
}

}
MattePozzy commented 10 months ago

I have found the issue. Inside the method "Valore" I manipulate the value. Ex:

        public VolosLabel Valore(Func<string> text)
        {
            string _text = text();
            _text = string.IsNullOrWhiteSpace(_text) ? "-" : _text;
            Value.Text(_text);
            return this;
        }

in this way the value is setted only the first time, then the binding with the State is lost.

If I use this way:

       public VolosLabel Valore(Func<string> text)
        {
            //string _text = text();
            //_text = string.IsNullOrWhiteSpace(_text) ? "-" : _text;
            //Value.Text(_text);
            Value.Text(text);
            return this;
        }

the binding is mainteined and the value is update according to the State value.

But I need to manipulate the value before set the Text property... I think I need to change the way I set the State.. or else I don't know exactly..

MattePozzy commented 10 months ago

just for completeness, i found a solution. What I wanted to do was this:

first I looked for the value in the datasource inside the Valore property and then I set the Text

public new VolosPicker Valore(Func<string> textFunc)
{
     ComboMobile comboSel = DS?.Find(x => x.Codice == textFunc());
     text.Value(() => comboSel?.Valore ?? "");
     return this;
}

the problem was that then the binding with the State was lost.

Now in the Valore method I set only the text

public new VolosPicker Valore(Func<string> textFunc)
{
     text.Value(textFunc);
     //ComboMobile comboSel = DS?.Find(x => x.Codice == textFunc());
     //text.Value(() => comboSel?.Valore ?? "");
     return this;
}

and on the State I create two properties instead of one:

Before:

internal class MainPageState
{
     public List<ComboMobile> DataSource { get; set; }
     public string Primo { get; set; } = "";
     public string Secondo{ get; set; } = "-";
}

After:

internal class MainPageState
{
     public List<ComboMobile> DataSource { get; set; }
     public string Primo { get; set; } = "";
     public string SecondoCod { get; set; } = "-";
     public string SecondoDescr { get => DataSource?.Find(x => x.Codice == SecondoCod)?.Valore ?? ""; }
}

I used to use State like this:

new VolosPicker()
     .Description("Secondo picker")
     .Value(() => State.Secondo)
     .DataSource(State.DataSource)

After:

new VolosPicker()
     .Description("Secondo picker")
     .Value(() => State.SecondoDescr)
     .DataSource(State.DataSource)

On the change of the first picker I haven't changed anything, I always go to set State.Secondo.

ezgif com-video-to-gif (3)

tcsaddul commented 10 months ago

I wish we can use this great library without these complications brought about by MVVM or MVU pattern. Just plain old C# coding without the patterns.

adospace commented 10 months ago

have you looked at the C# markup for dotnet maui? https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/markup/markup

seems what you're looking for