Salvador Cruz
Salvador Cruz

Reputation: 67

.NET Maui binding displays data on debug mode but not on release mode

I'm developing an app in .NET Maui and testing in a Android 14 phone, when I run it in debug mode data is displayed correctly, but when in Release mode data in the ClassNameView custom view and in the CollectionView is blank, I know that data is being loaded correctly, at least for the CollectionView, because there are as many rows as it should, but data is blank, if I put the XML of the custom view directly in the page then data is displayed as it should

What am I missing?

ObservationHistoryPage.xaml

<ContentPage
    x:Class="SchoolApp.Views.ObservationHistoryPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:custom="clr-namespace:SchoolApp.Custom"
    xmlns:resx="clr-namespace:SchoolApp.Resources.Strings"
    xmlns:skia="clr-namespace:SkiaSharp.Extended.UI.Controls;assembly=SkiaSharp.Extended.UI"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
    xmlns:vm="clr-namespace:SchoolApp.ViewModels"
    Title="{x:Static resx:AppResources.ObservationsHistory}"
    x:DataType="vm:ObservationHistoryPageViewModel">
    <ContentPage.Behaviors>
        <toolkit:EventToCommandBehavior Command="{Binding NavigatedToCommand}" EventName="NavigatedTo" />
    </ContentPage.Behaviors>
    <Grid>
        <custom:LoadingAndErrorView
            Display="{Binding Display}"
            ErrorDescription="{Binding ErrorMessage}"
            ErrorTitle="{Binding ErrorTitle}"
            RetryCommand="{Binding LoadInfoCommand}" />
        <ScrollView>
            <VerticalStackLayout
                Padding="10"
                IsVisible="{Binding DisplayData}"
                Spacing="10">
                <!--  Class Name  -->
                
                <custom:ClassNameView ClassName="{Binding ClassName}" />
                <Label
                    HorizontalOptions="Center"
                    Style="{StaticResource LargeLabelBold}"
                    Text="{x:Static resx:AppResources.ObservationHistory}" />
               
                <!--  Count  -->
                <HorizontalStackLayout Padding="0,0,5,0" HorizontalOptions="End">
                    <Label Style="{StaticResource MediumLabelItalic}" Text="Total:" />
                    <Label Style="{StaticResource MediumLabelItalic}" Text="{Binding ObservationCount}" />
                </HorizontalStackLayout>
                <!--  Dates  -->
                <CollectionView ItemsSource="{Binding Dates}" SelectionMode="None">
                    <CollectionView.ItemTemplate>
                        <DataTemplate>
                            <Grid Padding="10" ColumnDefinitions="80,*">
                                <Image
                                    HorizontalOptions="Center"
                                    Source="calendar"
                                    WidthRequest="68" />
                                <Label
                                    Grid.Column="1"
                                    HorizontalOptions="Center"
                                    Style="{StaticResource LargeLabelBold}"
                                    Text="{Binding ., StringFormat='{0:dd / MMMM / yyyy }'}"
                                    VerticalOptions="Center" />
                            </Grid>
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>
                <!--  close button  -->
                <Button
                    Command="{Binding CloseCommand}"
                    IsVisible="{Binding IsNotBusy}"
                    Style="{x:StaticResource ButtonOutline}"
                    Text="{x:Static resx:AppResources.Close}" />
            </VerticalStackLayout>
        </ScrollView>
    </Grid>
</ContentPage>

ObservationHistoryPageViewModel.cs

using SchoolApp.Models.Observations;

namespace SchoolApp.ViewModels
{
    [QueryProperty(nameof(Observation), nameof(Observation))]
    [QueryProperty(nameof(ClassName), nameof(ClassName))]
    public partial class ObservationHistoryPageViewModel : BaseViewModel
    {
        private readonly ObservationsService _observationsService;
        [ObservableProperty]
        ObservationStudentComplete _observation;
        
        [ObservableProperty]
        string _className;

        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(ObservationCount))]
        List<DateTime> _dates=new List<DateTime>();


        public int ObservationCount => Dates.Count;

        public ObservationHistoryPageViewModel(ObservationsService observationsService)
        {
            _observationsService = observationsService;
        }

        [RelayCommand]
        public async Task NavigatedTo()
        {
            await LoadInfo();
        }

        [RelayCommand]
        public async Task LoadInfo()
        {
            SetPageInLoadingState();
            var result = await _observationsService.GetObservationHistory(Selected.Student.IdAlumno, Selected.Organization.IsParent, Observation);
            SetDisplayAndErrorsFromResult(result);
            Dates = result.Item ?? new List<DateTime>();
            SetPageInFinishLoadingState();
        }

        [RelayCommand]
        public async Task Close()
        {
            await Shell.Current.GoToAsync("..");
        }
    }
}

Here is the custom view

ClassNameView.xaml

<Grid
    x:Class="SchoolApp.Custom.ClassNameView"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:custom="clr-namespace:SchoolApp.Custom"
    x:DataType="custom:ClassNameView"
    ColumnDefinitions="80,*">
    <Image Source="books" WidthRequest="60" />
    <Label
        Grid.Column="1"
        Style="{x:StaticResource LargeLabelBold}"
        Text="{Binding ClassName}"
        VerticalOptions="Center" />
</Grid>

ClassNameView.xaml.cs

namespace SchoolApp.Custom;

public partial class ClassNameView : Grid
{
    public static readonly BindableProperty ClassNameProperty = BindableProperty.Create(nameof(ClassName)
        , typeof(string)
        , typeof(ClassNameView)
        , default(string)
        , propertyChanged: (bindable, value, newValue) => ((ClassNameView)bindable).ClassName = (string)newValue);
    public string ClassName
    {
        get => (string)GetValue(ClassNameProperty);
        set => SetValue(ClassNameProperty, value);
    }
    public ClassNameView()
    {
        InitializeComponent();
    }
}

Upvotes: 0

Views: 241

Answers (3)

Sweathkumar
Sweathkumar

Reputation: 1

Solution to XA1030 Error: Disabling AOT Compilation and Trimming in Release Mode

If you encounter the error XA1030: The 'RunAOTCompilation' MSBuild property is only supported when trimming is enabled while building in Release mode, it’s because AOT (Ahead-of-Time) Compilation requires Trimming to be enabled.

If you don’t need AOT Compilation or Trimming, you can resolve this issue by disabling both in your .csproj file. Here’s how:

Fix in .csproj:

Modify your .csproj file for Release mode as follows:

<PropertyGroup Condition="'$(Configuration)'=='Release'">
    <PublishTrimmed>false</PublishTrimmed>  <!-- Disable trimming -->
    <RunAOTCompilation>false</RunAOTCompilation>  <!-- Disable AOT compilation -->
    <Optimize>true</Optimize> <!-- Enable optimization for Release -->
</PropertyGroup> 

Explanation:

  • PublishTrimmed=false: Disables trimming, meaning no unused code will be removed.

  • RunAOTCompilation=false: Disables AOT compilation, which is
    typically used to improve startup performance but requires trimming
    to be enabled.

  • Optimize=true: Enables code optimization for Release builds,
    allowing for better performance.

Final Steps:

Save the changes to your .csproj file.

Clean and Rebuild your project.

Test your app in Release mode to confirm that everything works as expected.

By following these steps, you should be able to build and run your app in Release mode without encountering the XA1030 error.

Upvotes: 0

H.A.H.
H.A.H.

Reputation: 3897

For your empty collection, you should check this: https://stackoverflow.com/a/75285858/6643940

For your grid control, I have different solution.

Usually, when you override Grid, you are trying to create control that have different behavior. That is, it will be expected that you can do:

<MyGrid> <Something> </MyGrid> 

And there would be something different there - either you will have new functionality of grid, or change of existing functionality.

If you are just trying to make a custom control, that have predefined look, you can simply make control template.

https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/controltemplate?view=net-maui-8.0

  1. Move your XAML to control template, set the binding context of the grid to templated parent.
  2. Do not override Grid, just ContentView in your control code.
  3. Set the Template key to your page xaml, where you create the control.

Upvotes: 2

Bhavanesh N
Bhavanesh N

Reputation: 1255

propertyChanged: (bindable, value, newValue) => ((ClassNameView)bindable).ClassName = (string)newValue);

You're assigning value to ClassName in it's PropertyChanged Event. Which will again fire PropertyChanged. Hence creating a infinite cycle.

And also, you need to set

BindingContext = this;

for your custom control ClassNameView. Then only Label's text will be shown.

Upvotes: 0

Related Questions