asp.net-coreblazorinject

Injecting a custom service into a hierarchy of components


I have a singleton service that I am passing as a parameter into a Index.razor. Index.razor is re-rendered when I clear the counter. When I pass the same service to Component1 and click the Increase Count button the page is not re-rendered. If I reload the page I can see the Counter increase.

Thank you for your assistance.

PS. I am not able to format the MyService class properly. I tried several times. My apologies. I am new to Stack Overflow.

Service

namespace Injection.Pages

{ public class MyService { public int Counter { get; set; } public void increaseCount() { Counter = Counter + 1;

    }

    public void clearCounter()
    {
        Counter = 0;
    }

}

}

Index
@page "/" @inject MyService myService

<h3>Injection</h3>

<button @onclick="clearCounter">Clear Count</button>
<br />
<br />

@myService.Counter

<Component1 myService="myService" />

@code
{
    private void clearCounter ()
    {
        myService.clearCounter();
        StateHasChanged();
    }
}

Component

    <h3>Component1</h3>

<button @onclick="increaseCount">Increase Count</button>

@code {
    [Parameter]
    public MyService myService { get; set; }

    private void increaseCount()
    {
        myService.increaseCount();
        StateHasChanged();
    }
}

Solution

  • In summary, though you have set the state, the change is not notified between components. Here is a sample.

    Service

    public class MyService
    {
        public int Counter { get; set; }
        public Action OnChange { get; set; }
    
        public void increaseCount()
        {
            Counter += 1;
            NotifyStateChanged();
        }
    
        public void clearCounter()
        {
            Counter = 0;
            NotifyStateChanged();
        }
    
        private void NotifyStateChanged()
        {
            var task = Task.Run(() => OnChange?.Invoke());
        }
    
    }
    

    Home

    @page "/"
    @using BlazorApp71.Components.Pages
    @inject MyService myService
    
    <h3>Injection</h3>
    
    <button @onclick="clearCounter">Clear Count</button>
    <br />
    <br />
    
    @myService.Counter
    
    <Component1 myService="myService" />
    
    @code
    {
        protected override void OnInitialized()
        {
            myService.OnChange += async () => await InvokeAsync(StateHasChanged);
        }
    
        private void clearCounter()
        {
            myService.clearCounter();
        }
    
        public void Dispose()
        {
            myService.OnChange -= async () => await InvokeAsync(StateHasChanged);
        }
    }
    

    Component

    <h3>Component1</h3>
    
    <button @onclick="increaseCount">Increase Count</button>
    
    @code {
        [Parameter]
        public MyService myService { get; set; }
    
        protected override void OnInitialized()
        {
            myService.OnChange += async () => await InvokeAsync(StateHasChanged);
        }
    
        private void increaseCount()
        {
            myService.increaseCount();
        }
    
        public void Dispose()
        {
            myService.OnChange += async () => await InvokeAsync(StateHasChanged);
        }
    }
    

    There are some other approaches to communicate between components https://chrissainty.com/3-ways-to-communicate-between-components-in-blazor/ . You can refer to this for more information.