Observable properties and collections reflect modifications as expected in MAUI XAML Page but not in Blazor components

126 views Asked by At

I have a view model that gets injected as a singleton both in MAUI pages and Blazor components:

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    double? fixedIntervalStartAt;

    [ObservableProperty]
    ObservableCollection<PunchCardEntry> items = new ObservableCollection<PunchCardEntry>();

    public async Task Update()
    {
        // populate and update above properties and collection items
    }
}

public partial class PunchCardEntry : ObservableObject
{
    [ObservableProperty]
    DateTime dueTime;

    [ObservableProperty]
    string name;

    [ObservableProperty]
    EntryStatus status = EntryStatus.Scheduled;

    [ObservableProperty]
    bool alarmEnabled = true;
}

Update() gets called both by MAUI page method and Blazor components. In both cases, only the XAML page reflects the changes in the data:

XAML sample (this works as expected):

<CollectionView ItemsSource="{Binding Items,Converter={StaticResource collectionPaginationConverter},ConverterParameter=1}">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="models:PunchCardEntry">
            <Border BackgroundColor="{Binding Status, Converter={StaticResource enumToColorConverter}}" Padding="12,10" Margin="0,0,0,10"  StrokeThickness="0">
                <Border.StrokeShape>
                    <RoundRectangle CornerRadius="10" />
                </Border.StrokeShape>
                <Border.Shadow>
                    <Shadow Brush="Black"
                            Offset="1,1"
                            Radius="5"
                            Opacity="0.3" />
                </Border.Shadow>

                <Grid ColumnDefinitions="80,*,70" RowSpacing="10">
                    <FlexLayout Grid.Column="0" AlignItems="Center" Direction="Column" JustifyContent="Center">
                        <Image Source="{Binding AlarmEnabled , Converter={StaticResource boolToImageConverter}}" WidthRequest="48" HeightRequest="48"/>
                    </FlexLayout >
                    <StackLayout  Grid.Column="1">
                        <Label Text="{Binding Name}" TextTransform="Uppercase" FontFamily="SubtitleFont" FontSize="14"  />
                        <Label Text="{Binding DueTime, StringFormat='{0:t}'}" FontFamily="TitleFont" FontSize="30" FontAttributes="Bold" />
                    </StackLayout>
                    <FlexLayout Grid.Column="2" AlignItems="Center" Direction="Column" JustifyContent="Center">
                        <Image Source="{Binding Status, Converter={StaticResource enumToImageConverter}}" WidthRequest="48" HeightRequest="48"/>
                    </FlexLayout>
                </Grid>
            </Border>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Blazor Components (does not reflect updates):

@inject MainViewModel viewModel

@if (Cards == null || !Cards.Any())
{
    <div>Loading...</div>
}
else
{
    <MudStack>
        @foreach (var card in Cards)
        {
            <MudItem xs="12">
                <PunchCard Card="@card"/>
            </MudItem>
        }
    </MudStack>
}

@code {
    ObservableCollection<PunchCardEntry> Cards;

    protected override void OnInitialized()
    {
        Cards = viewModel.Items;
        base.OnInitialized();
    }
}

PunchCard component (referenced in the code above):

<MudPaper>
<div>
    <div><MudIcon Icon="@(Card.AlarmEnabled ? Icons.Material.TwoTone.AlarmOn : Icons.Material.TwoTone.AlarmOff)" Size="Size.Large" /></div>
    <div>
        <div>
            <MudText >@Card.Name.ToUpper()</MudText>
            <MudText >@Card.DueTime.ToShortTimeString()</MudText>
        </div>
    </div>
    <div >
        <MudIcon Icon="@(Card.Status == EntryStatus.Scheduled
            ? Icons.Material.TwoTone.Schedule
            : (Card.Status == EntryStatus.Pending
                ? Icons.Material.TwoTone.Error
                : Icons.Material.TwoTone.CheckCircle))"
            Size="Size.Large" />
    </div>
</div>
</MudPaper>

@code {
    [Parameter]
    public PunchCardEntry Card { get; set; }
}

What am I missing?

0

There are 0 answers