My question is why does it take so long to load the data to a collection or component? I use this same logic in xamarin form and it takes almost nothing.
Or is it done differently here?
ViewModel
public DetalleMensualViewModel()
{
Sales = new ObservableCollection<DetalleMensual>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
}
async Task ExecuteLoadItemsCommand()
{
await CargarInformacionMensual();
await CargarVentasPorMes();
}
async Task CargarInformacionMensual()
{
DateTime date = DateTime.Parse(ItemId);
int inversionTotal = 0;
int ventaTotal = 0;
using (var db = new Services.AppDbContext())
{
// Total Mes Anterior
decimal totalVentas = await db.AppSale
.Where(w => w.CreateDate < date)
.SumAsync(s => (decimal?)s.VentaTotal) ?? 0M;
ventaTotal = (int)totalVentas; // Formateo con separador de miles
totalVentas = db.AppSale
.Where(w => w.CreateDate < date)
.Sum(s => (decimal?)s.InversionTotal) ?? 0M;
inversionTotal = (int)totalVentas;
Total = ventaTotal - inversionTotal;
// Lo que se vendio en el mes
totalVentas = await db.AppSale
.Where(w => w.CreateDate.Month == date.Month && w.CreateDate.Year == date.Year)
.SumAsync(s => (decimal?)s.VentaTotal) ?? 0M;
Ganancia = (int)totalVentas; // Formateo con separador de miles
// Lo que se invirtio en el mes
totalVentas = await db.AppSale
.Where(w => w.CreateDate.Month == date.Month && w.CreateDate.Year == date.Year)
.SumAsync(s => (decimal?)s.InversionTotal) ?? 0M;
Inversion = (int)totalVentas; // Formateo con separador de miles
TotalMes = Ganancia - Inversion;
//Total de todo (CORREGIR)
TotalComputo = Total + Ganancia - Inversion; // Formateo con separador de miles
}
}
async Task CargarVentasPorMes()
{
IsBusy = false;
IsSpinner = true;
Sales.Clear();
try
{
DateTime date = DateTime.Parse(ItemId);
string nombreMes = date.ToString("MMMM yyyy", new System.Globalization.CultureInfo("es-ES"));
Title = nombreMes;
List<DetalleMensual> detalleMensual;
Title = nombreMes;
//int total = "$0";
using (var db = new Services.AppDbContext())
{
detalleMensual = await db.AppSaleDetail
.Join(db.AppProduct,
saleDetail => saleDetail.ProductId,
product => product.Id,
(saleDetail, product) => new { saleDetail, product })
.Where(joined => joined.saleDetail.CreateDate.Month == date.Month &&
joined.saleDetail.CreateDate.Year == date.Year)
.OrderByDescending(joined => joined.saleDetail.CreateDate)
.Select(joined => new DetalleMensual
{
Id = joined.saleDetail.Id,
SaleId = joined.saleDetail.SaleId,
Nombre = $"{joined.saleDetail.Quantity} x {(joined.product.Nombre.Length > 25 ? $"{joined.product.Nombre.Substring(0, 25)}....." : joined.product.Nombre)}",
Precio = joined.product.Precio,
Cantidad = joined.saleDetail.Quantity,
CreateDate = joined.saleDetail.CreateDate,
CodigoBarra = joined.product.CodigoBarra,
Descripcion = joined.product.Descripcion,
Total = joined.saleDetail.Total,
TipoVenta = joined.saleDetail.TipoVenta,
})
//.Take(25)
.ToListAsync();
}
//Sales = new ObservableCollection<DetalleMensual>(detalleMensual);
foreach (var item in detalleMensual)
{
Sales.Add(item);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
IsSpinner = false;
UpdatedAt = DateTime.Now;
}
}
View:
<RefreshView Padding="0, 10, 0, 0" x:DataType="local:DetalleMensualViewModel" Command="{Binding LoadItemsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<ScrollView AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All">
<StackLayout>
<StackLayout Padding="20" BackgroundColor="{StaticResource Primary}">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
<Image Source="today.png" WidthRequest="25" HeightRequest="20" Aspect="AspectFit" />
<Label Text="{Binding Title}" FontSize="16" TextColor="White" FontAttributes="Bold" />
</StackLayout>
<Label Text="Ultima actualizacion" FontSize="12" TextColor="White" FontAttributes="None" HorizontalTextAlignment="Center" />
<Label Text="{Binding UpdatedAt}" FontSize="12" TextColor="White" FontAttributes="Italic" HorizontalTextAlignment="Center"/>
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row = "1" Grid.Column="0" Text="Ingreso mes actual" FontSize="13" TextColor="White" />
<Label Grid.Row = "1" Grid.Column="1" Text="{Binding Ganancia, StringFormat='${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
<Label Grid.Row = "2" Grid.Column="0" Text="Inversion mes actual" FontSize="13" TextColor="White" />
<Label Grid.Row = "2" Grid.Column="1" Text="{Binding Inversion, StringFormat='-${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
</Grid>
<BoxView VerticalOptions="Center" Grid.Row = "2" HeightRequest="1" Color="LightGray" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row = "0" Text="{Binding Title, StringFormat='Ganancia {0}'}" FontSize="13" TextColor="White" />
<Label Grid.Column="1" Grid.Row = "0" Text="{Binding TotalMes, StringFormat='${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
<Label Grid.Column="0" Grid.Row = "1" Text="Total mes anterior" FontSize="13" TextColor="White" />
<Label Grid.Column="1" Grid.Row = "1" Text="{Binding Total, StringFormat='+${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
</Grid>
<BoxView VerticalOptions="Center" HeightRequest="1" Color="LightGray" />
<Grid>
<Label Grid.Column="0" Grid.Row = "0" Text="Total mes anterior" FontSize="13" TextColor="White" />
<Label Grid.Column="1" Grid.Row = "0" Text="{Binding TotalComputo, StringFormat='${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
</Grid>
</StackLayout>
<CollectionView x:Name="ItemsListView" ItemsSource="{Binding Sales}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:DetalleMensual">
<StackLayout Padding="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="260"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding Nombre}" FontSize="Small" FontAttributes="Bold" />
<StackLayout Grid.Row="0" Grid.Column="1" Orientation="Horizontal" HorizontalOptions="End">
<Label Text="{Binding Total, StringFormat='${0:N0}'}" FontSize="Small" HorizontalTextAlignment="End" TextColor="Green" FontAttributes="Bold">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding TipoVenta}" Value="Inversión">
<Setter Property="TextColor" Value="Red"/>
<Setter Property="Text" Value="{Binding Total, StringFormat='-${0:N0}'}" />
</DataTrigger>
</Label.Triggers>
</Label>
</StackLayout>
<Label Grid.Row="1" Grid.Column="0" Text="{Binding CreateDate}" FontSize="Small" FontAttributes="None" />
<Label Grid.Row="1" Grid.Column="1" Text="{Binding TipoVenta}" HorizontalTextAlignment="End" FontSize="14" TextColor="Green">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding TipoVenta}" Value="Inversión">
<Setter Property="TextColor" Value="Red"/>
</DataTrigger>
</Label.Triggers>
</Label>
<Label Grid.Row="2" Text="{Binding CodigoBarra}" FontSize="Small" FontAttributes="None" />
</Grid>
<BoxView VerticalOptions="Center" HeightRequest="1" Color="LightGray" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
<!-- Indicador de actividad centrado -->
<ActivityIndicator IsVisible="{Binding IsSpinner}" IsRunning="{Binding IsSpinner}"
Color="Black"
AbsoluteLayout.LayoutBounds="0.5,0.5,0.1,0.1"
AbsoluteLayout.LayoutFlags="All" />
</AbsoluteLayout>
</RefreshView>
When I query the database, it does not delay the query. The problem comes after using.
Faster loading views
My question is why does it take so long to load the data to a collection or component? I use this same logic in xamarin form and it takes almost nothing.
Or is it done differently here?
ViewModel
public DetalleMensualViewModel()
{
Sales = new ObservableCollection<DetalleMensual>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
}
async Task ExecuteLoadItemsCommand()
{
await CargarInformacionMensual();
await CargarVentasPorMes();
}
async Task CargarInformacionMensual()
{
DateTime date = DateTime.Parse(ItemId);
int inversionTotal = 0;
int ventaTotal = 0;
using (var db = new Services.AppDbContext())
{
// Total Mes Anterior
decimal totalVentas = await db.AppSale
.Where(w => w.CreateDate < date)
.SumAsync(s => (decimal?)s.VentaTotal) ?? 0M;
ventaTotal = (int)totalVentas; // Formateo con separador de miles
totalVentas = db.AppSale
.Where(w => w.CreateDate < date)
.Sum(s => (decimal?)s.InversionTotal) ?? 0M;
inversionTotal = (int)totalVentas;
Total = ventaTotal - inversionTotal;
// Lo que se vendio en el mes
totalVentas = await db.AppSale
.Where(w => w.CreateDate.Month == date.Month && w.CreateDate.Year == date.Year)
.SumAsync(s => (decimal?)s.VentaTotal) ?? 0M;
Ganancia = (int)totalVentas; // Formateo con separador de miles
// Lo que se invirtio en el mes
totalVentas = await db.AppSale
.Where(w => w.CreateDate.Month == date.Month && w.CreateDate.Year == date.Year)
.SumAsync(s => (decimal?)s.InversionTotal) ?? 0M;
Inversion = (int)totalVentas; // Formateo con separador de miles
TotalMes = Ganancia - Inversion;
//Total de todo (CORREGIR)
TotalComputo = Total + Ganancia - Inversion; // Formateo con separador de miles
}
}
async Task CargarVentasPorMes()
{
IsBusy = false;
IsSpinner = true;
Sales.Clear();
try
{
DateTime date = DateTime.Parse(ItemId);
string nombreMes = date.ToString("MMMM yyyy", new System.Globalization.CultureInfo("es-ES"));
Title = nombreMes;
List<DetalleMensual> detalleMensual;
Title = nombreMes;
//int total = "$0";
using (var db = new Services.AppDbContext())
{
detalleMensual = await db.AppSaleDetail
.Join(db.AppProduct,
saleDetail => saleDetail.ProductId,
product => product.Id,
(saleDetail, product) => new { saleDetail, product })
.Where(joined => joined.saleDetail.CreateDate.Month == date.Month &&
joined.saleDetail.CreateDate.Year == date.Year)
.OrderByDescending(joined => joined.saleDetail.CreateDate)
.Select(joined => new DetalleMensual
{
Id = joined.saleDetail.Id,
SaleId = joined.saleDetail.SaleId,
Nombre = $"{joined.saleDetail.Quantity} x {(joined.product.Nombre.Length > 25 ? $"{joined.product.Nombre.Substring(0, 25)}....." : joined.product.Nombre)}",
Precio = joined.product.Precio,
Cantidad = joined.saleDetail.Quantity,
CreateDate = joined.saleDetail.CreateDate,
CodigoBarra = joined.product.CodigoBarra,
Descripcion = joined.product.Descripcion,
Total = joined.saleDetail.Total,
TipoVenta = joined.saleDetail.TipoVenta,
})
//.Take(25)
.ToListAsync();
}
//Sales = new ObservableCollection<DetalleMensual>(detalleMensual);
foreach (var item in detalleMensual)
{
Sales.Add(item);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
IsSpinner = false;
UpdatedAt = DateTime.Now;
}
}
View:
<RefreshView Padding="0, 10, 0, 0" x:DataType="local:DetalleMensualViewModel" Command="{Binding LoadItemsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<ScrollView AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All">
<StackLayout>
<StackLayout Padding="20" BackgroundColor="{StaticResource Primary}">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
<Image Source="today.png" WidthRequest="25" HeightRequest="20" Aspect="AspectFit" />
<Label Text="{Binding Title}" FontSize="16" TextColor="White" FontAttributes="Bold" />
</StackLayout>
<Label Text="Ultima actualizacion" FontSize="12" TextColor="White" FontAttributes="None" HorizontalTextAlignment="Center" />
<Label Text="{Binding UpdatedAt}" FontSize="12" TextColor="White" FontAttributes="Italic" HorizontalTextAlignment="Center"/>
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row = "1" Grid.Column="0" Text="Ingreso mes actual" FontSize="13" TextColor="White" />
<Label Grid.Row = "1" Grid.Column="1" Text="{Binding Ganancia, StringFormat='${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
<Label Grid.Row = "2" Grid.Column="0" Text="Inversion mes actual" FontSize="13" TextColor="White" />
<Label Grid.Row = "2" Grid.Column="1" Text="{Binding Inversion, StringFormat='-${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
</Grid>
<BoxView VerticalOptions="Center" Grid.Row = "2" HeightRequest="1" Color="LightGray" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row = "0" Text="{Binding Title, StringFormat='Ganancia {0}'}" FontSize="13" TextColor="White" />
<Label Grid.Column="1" Grid.Row = "0" Text="{Binding TotalMes, StringFormat='${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
<Label Grid.Column="0" Grid.Row = "1" Text="Total mes anterior" FontSize="13" TextColor="White" />
<Label Grid.Column="1" Grid.Row = "1" Text="{Binding Total, StringFormat='+${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
</Grid>
<BoxView VerticalOptions="Center" HeightRequest="1" Color="LightGray" />
<Grid>
<Label Grid.Column="0" Grid.Row = "0" Text="Total mes anterior" FontSize="13" TextColor="White" />
<Label Grid.Column="1" Grid.Row = "0" Text="{Binding TotalComputo, StringFormat='${0:N0}'}" FontSize="13" TextColor="White" HorizontalTextAlignment="End" />
</Grid>
</StackLayout>
<CollectionView x:Name="ItemsListView" ItemsSource="{Binding Sales}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:DetalleMensual">
<StackLayout Padding="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="260"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding Nombre}" FontSize="Small" FontAttributes="Bold" />
<StackLayout Grid.Row="0" Grid.Column="1" Orientation="Horizontal" HorizontalOptions="End">
<Label Text="{Binding Total, StringFormat='${0:N0}'}" FontSize="Small" HorizontalTextAlignment="End" TextColor="Green" FontAttributes="Bold">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding TipoVenta}" Value="Inversión">
<Setter Property="TextColor" Value="Red"/>
<Setter Property="Text" Value="{Binding Total, StringFormat='-${0:N0}'}" />
</DataTrigger>
</Label.Triggers>
</Label>
</StackLayout>
<Label Grid.Row="1" Grid.Column="0" Text="{Binding CreateDate}" FontSize="Small" FontAttributes="None" />
<Label Grid.Row="1" Grid.Column="1" Text="{Binding TipoVenta}" HorizontalTextAlignment="End" FontSize="14" TextColor="Green">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding TipoVenta}" Value="Inversión">
<Setter Property="TextColor" Value="Red"/>
</DataTrigger>
</Label.Triggers>
</Label>
<Label Grid.Row="2" Text="{Binding CodigoBarra}" FontSize="Small" FontAttributes="None" />
</Grid>
<BoxView VerticalOptions="Center" HeightRequest="1" Color="LightGray" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
<!-- Indicador de actividad centrado -->
<ActivityIndicator IsVisible="{Binding IsSpinner}" IsRunning="{Binding IsSpinner}"
Color="Black"
AbsoluteLayout.LayoutBounds="0.5,0.5,0.1,0.1"
AbsoluteLayout.LayoutFlags="All" />
</AbsoluteLayout>
</RefreshView>
When I query the database, it does not delay the query. The problem comes after using.
Faster loading views
Share Improve this question edited Mar 19 at 15:09 Felipe Peña asked Mar 19 at 15:08 Felipe PeñaFelipe Peña 12 bronze badges 8- what does "so long" actually mean? 5s? 10s? Have you profiled your code to determine where the slowdown actually is? – Jason Commented Mar 19 at 15:21
- I was debugging the code and it slows down after the database call, when loading the collection. I use this same logic in xamarin.form and I don't have this problem. In xamarin.form it takes about 2 seconds. here in maui about 6 seconds approximately(They are the same query and the same View). – Felipe Peña Commented Mar 19 at 17:14
- use Stopwatch to actually time your code to figure out the source of the problem. If I had to guess I'd say that adding items to the Collection one at a time is the source, but the key to tracking down any performance issue is to start with reliable data. – Jason Commented Mar 19 at 18:07
- I think the same thing, adding one at a time may take a while, since the query does not take as long with 45 data. – Felipe Peña Commented Mar 19 at 18:24
- Do you have an alternative way to upload the data? – Felipe Peña Commented Mar 19 at 18:32
1 Answer
Reset to default -1- Try to change
Sales
to a plain oddList<DetalleMensual
(needs to raise property changed in property setter, if not already done). - Assign
Sales
just once (callingAdd
on aObservableCollection
might add unnecessary layout cycles)