Blazor Multiple change events not updating property correctly

0

I am new to blazor, and excited to start trying it for some of our internal applications, however I am having some trouble understanding the binding/change events. Starting with a new Blazor project I added a AppService singleton and inject that service into a new page (buildings) and my navmenu. On both the navmenu and building page I have a checkbox bound to the service property ie.

When I change the checkbox it updates the service property on that page, but it does not update the property on the content area page. What am I doing incorrectly?

Update: I did try to implement the solution here: Blazor - razor page not updating after property from DI Service is changed , but unfortunately when I do my application will not even run. =( (The program '[26772] iisexpress.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.)

AppService.

public class AppService 
{
    public bool IsAdmin { get; set; } = true;
    public event Action OnChange;
    private void NotifyDataChanged() => OnChange?.Invoke();
}

Startup.cs Configure Services Method

services.AddSingleton<Services.AppService>();

NavMenu.

@inject Services.AppService AppService
<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">Staff Management</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<ul class="nav flex-column">
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
            <span class="oi oi-home" aria-hidden="true"></span> Home
        </NavLink>
    </li>
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="counter">
            <span class="oi oi-plus" aria-hidden="true"></span> Counter
        </NavLink>
    </li>
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="fetchdata">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
        </NavLink>
    </li>
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="/buildings">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Buildings
        </NavLink>
    </li>
    <li class="nav-item px-3">
        IsAdmin: <input type="checkbox" @bind="@AppService.IsAdmin" />
        <span style="color:#fff;">@AppService.IsAdmin</span>
    </li>
</ul>
</div>

@code {
private bool collapseNavMenu = true;

private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

private void ToggleNavMenu()
{
    collapseNavMenu = !collapseNavMenu;
}

private void AdminChanged()
{
    AppService.IsAdmin = !AppService.IsAdmin;
    //trying to manually call state change here since below wasn't working
    StateHasChanged();
}

protected override void OnInitialized()
{
    AppService.OnChange += AdminChanged; //also tried AppService.OnChange += StateHasChanged;
}
}

Buildings.razor

@page "/buildings"
@inject Services.AppService AppService
<h3>Buildings IsAdmin: @AppService.IsAdmin</h3>

<input type="checkbox" @bind="@AppService.IsAdmin"/>
@code {

protected override void OnInitialized()
{
    AppService.OnChange += StateHasChanged;
}
}

Overall what I am trying to achieve is this: Create a property that I can utilize in all of my pages/components to conditionally display/do operations.

I would expect that if i click the checkbox on the buildings page the navmenu would be updated with the new value from the service, but doesn't happen. OR clicking the checkbox on navmenu would update the buildings.razor page.

Any help is greatly appreciated. Maybe I am not understanding something correctly. Thanks!!

.net
asp.net-core
razor
dependency-injection
blazor
asked on Stack Overflow Jan 24, 2020 by John Dover • edited Jan 24, 2020 by John Dover

1 Answer

1

This might be related to the fact that your service does not trigger the event at all. The IsAdmin property should check if its value has changed, and if it does, it should raise the event. Try this code snippet. Notify the type of the event handler NotifyDataChanged ... It is Func<Task>

public class AppService 
{
   private bool isAdmin = true;
   public bool IsAdmin 
   { 
     get { return isAdmin; }
     set 
     { 
        if(isAdmin != value)
        {
            isAdmin = value; 

            if (NotifyDataChanged != null)
            {
                await NotifyDataChanged?.Invoke();
            }
        }
     } 
   } 
   public event Func<Task> NotifyDataChanged;

 }

Buildings.razor

@page "/buildings"
@inject Services.AppService AppService
@implements IDisposable 

<h3>Buildings IsAdmin: @AppService.IsAdmin</h3>

<input type="checkbox" @bind="@AppService.IsAdmin"/>
@code {

    public async Task OnNotifyDataChanged()
    {
        await InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }


    protected override void OnInitialized()
    {
        AppService.NotifyDataChanged += OnNotifyDataChanged;
    }
    public void Dispose()
    {
        AppService.NotifyDataChanged -= OnNotifyDataChanged;
    }

Try and report...

answered on Stack Overflow Jan 24, 2020 by enet

User contributions licensed under CC BY-SA 3.0