ListView items doesn't appear Xamarin Forms - c#

Good morning!
I've a big problem with ListViews in Xamarin Forms: my items aren't shown.
This is my xml code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="KOTC.Views.News">
<ContentPage.Content>
<StackLayout>
<ListView x:Name="list" HasUnevenRows="true" IsVisible="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Text ="{Binding title}" Grid.Row="0" VerticalOptions="CenterAndExpand" FontSize="10" TextColor="Black"/>
<Label Text="{Binding date}" Grid.Row="1" FontSize="10"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
and this is my class constructor:
public News()
{
InitializeComponent();
ObservableCollection<ListNewsItem> listNews = new ObservableCollection<ListNewsItem>();
RemoteDBConnection conn = new RemoteDBConnection(QUERY);
conn.Connect();
List<Models.News> news = conn.ExecuteQueryWithResponse(QUERY);
for (int i = 0; i < news.Count; i++)
{
ListNewsItem item = new ListNewsItem
{
date = news[i].publicationDate,
title = news[i].title
};
listNews.Add(item);
}
list.ItemsSource = listNews;
}
In this moment method ExecuteQueryWithResponse() returns 3 items, that are detected by ListView, in fact when I start the app, I see 3 ViewCells. The problem is that these viewcells are empty, they're not showing data.
Someone can help me?

Related

XAMARIN: Dynamically create entries with button click

I am quite new to this, but I am trying to figure out how to dynamically add entries with a button click.
I am creating new entries with each button click but my issue is that the entries are placed under the button instead of ontop of it.
Here is how my app looks like:
[![enter image description here][1]][1]
By clicking the `Add Ingredient` button, I want to add a new entry.
This is what the front end looks like:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EasyChef.Views.AboutPage"
xmlns:vm="clr-namespace:EasyChef.ViewModels"
Title="{Binding Title}">
<ContentPage.BindingContext>
<vm:AboutViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="Accent">#96d1ff</Color>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout BackgroundColor="{StaticResource Accent}" VerticalOptions="FillAndExpand" HorizontalOptions="Fill">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center">
<ContentView Padding="0,40,0,40" VerticalOptions="FillAndExpand">
<Label Text="EasyChef" TextColor="Black" FontSize="24" FontAttributes="Bold" Margin="10"/>
</ContentView>
</StackLayout>
</StackLayout>
<ScrollView Grid.Row="1">
<StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10">
<Label Text="Simply select ingredients!" FontSize="Title"/>
<StackLayout x:Name="EntriesStackLayout">
<Grid VerticalOptions="CenterAndExpand" Margin="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Entry Placeholder="Eg. Eggs" x:Name="EntryTag" Grid.Row="0"/>
<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>
</Grid>
</StackLayout>
<CheckBox />
</StackLayout>
</ScrollView>
</Grid>
</ContentPage>
And the back end()
public partial class AboutPage : ContentPage
{
int x = 1;
public AboutPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
AddEntry(EntriesStackLayout, "Ingredient " + x.ToString());
x++;
}
private void AddEntry(StackLayout sl, string name)
{
Entry entry = new Entry()
{
Placeholder = name,
};
sl.Children.Add(entry);
}
}
My preferred solution would be to create new entries with each button click, but I am happy with having default entries and unhiding them in order with a click.
A simple method is to move the Button to the outside of the StackLayout(StackLayout x:Name="EntriesStackLayout") and below the StackLayout.
Please refer to the following code:
<ScrollView Grid.Row="1">
<StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10">
<Label Text="Simply select ingredients!" FontSize="Title"/>
<StackLayout x:Name="EntriesStackLayout">
<Grid VerticalOptions="CenterAndExpand" Margin="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Entry Placeholder="Eg. Eggs" x:Name="EntryTag" Grid.Row="0"/>
<!--<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>-->
</Grid>
</StackLayout>
<!--move button here-->
<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>
<CheckBox />
</StackLayout>
</ScrollView>

Xamarin - ListView showing all property values but one

I have a Content Page in which I want to show an invoice, for that I have two listviews.
The first one contains the name of the customer, the date and the total cost.
The thing is to get the total cost I have used Shell navigation with parameters and it works fine just not in the listview.
So here is my ViewModel
[QueryProperty(nameof(Total), "total")]
public class InvoiceViewModel : BindableObject
{
string _total;
public string Total
{
get => _total;
set
{
_total = Uri.UnescapeDataString(value ?? string.Empty);
OnPropertyChanged();
}
}
public InvoiceViewModel()
{
_oListOrders = new ObservableCollection<CrOrder>();
GetListCart();
}
private ApiService _apiService = new ApiService();
public List<Invoice> _oListCart = new List<Invoice>();
public ObservableCollection<CrOrder> _oListOrders;
public List<Invoice> ListCart
{
get => _oListCart;
set
{
_oListCart = value;
OnPropertyChanged();
}
}
private async void GetListCart()
{
// call database here
var customerId = Convert.ToInt32(CurrentPropertiesService.GetCustomer());
var customer = await _apiService.GetCustomerById(customerId, CurrentPropertiesService.GetToken());
_oListCart.Add(new Invoice
{
Name = customer.Data.Name,
Date = DateTime.UtcNow,
Total = Convert.ToDecimal(_total),
ListOrders = await GetListOrders()
});
}
private async Task<ObservableCollection<CrOrder>> GetListOrders()
{
// call database here
var cartId = Convert.ToInt32(CurrentPropertiesService.GetCart());
var orders = await _apiService.GetOrdersByCart(cartId, CurrentPropertiesService.GetToken());
ObservableCollection<CrOrder> collection = new ObservableCollection<CrOrder>(orders.Data);
return collection;
}
}
Here is what I have in my View
<ContentPage.Content>
<StackLayout BackgroundColor="#A7A7A7">
<Label Text="{Binding Total}" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"></Label>
<ListView x:Name="ListViewCart" ItemsSource="{Binding ListCart}" HasUnevenRows="True" IsPullToRefreshEnabled="False" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:Invoice">
<ViewCell>
<Frame HasShadow="True" Margin="2" BorderColor="Gray">
<Grid Margin="0" HorizontalOptions="FillAndExpand" VerticalOptions="Center" HeightRequest="150" RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Nombre del Cliente:" VerticalOptions="Start"/>
<Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Name}" VerticalOptions="Start"/>
<Label Grid.Row="1" Grid.Column="0" Text="Fecha Compra:" VerticalOptions="Start"/>
<Label Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Date}" VerticalOptions="Start"/>
<Label Grid.Row="2" Grid.Column="0" Text="Monto Total:" VerticalOptions="Start"/>
<Label Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Total, StringFormat='{0:N2}€'}" VerticalOptions="Start"/>
<Label Grid.Row="3" Grid.ColumnSpan="3" Text="Detalle Compra" VerticalOptions="Start"/>
<BoxView Grid.Row="4" Grid.ColumnSpan="3" Color="Gray" HeightRequest="2" HorizontalOptions="Fill" />
<Label Grid.Row="5" Grid.Column="0" Text="Nombre" VerticalOptions="Start" TextColor="#9C2424"/>
<Label Grid.Row="5" Grid.Column="1" Text="Monto" VerticalOptions="Start" TextColor="#9C2424"/>
<Label Grid.Row="5" Grid.Column="2" Text="Cantidad" VerticalOptions="Start" TextColor="#9C2424"/>
<StackLayout Grid.Row="6" Grid.ColumnSpan="3" Margin="0" Padding="0">
<ListView x:Name="ListViewOrders" ItemsSource="{Binding ListOrders}" HasUnevenRows="True" IsPullToRefreshEnabled="False" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:CrOrder">
<ViewCell IsEnabled="False">
<Grid RowSpacing="0" ColumnSpacing="0" Margin="0" MinimumHeightRequest="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Reference}" TextColor="Black" VerticalOptions="Center" FontSize="12" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Price, StringFormat='{0:N2}€'}" TextColor="Black" VerticalOptions="End" FontSize="12" />
<Label Grid.Row="0" Grid.Column="2" Text="{Binding Quantity}" TextColor="Black" VerticalOptions="End" FontSize="12"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>...
And on my ContentPage I don't have anything
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class InvoicePage : ContentPage
{
public InvoicePage()
{
InitializeComponent();
//BindingContext = new InvoiceViewModel();
}
}
So on my View I have put a label to check what I thought was happening. So the label shows right the total but when I use the ListView binging it doesn't work I don't know why it is null there.
As you can see the label works fine but where it sais "Monto Total" it shows nothing. Please help I don't know what is going on. Thanks.
EDIT
I tried naming the Total property different and then when I add my Invoice entity to my list I do this
Total = Convert.ToDecimal(TotalCart),
But it isn't working eitherway. I don't know why the first time it returns the value fine but the second it doesn't.
After debbuging I have realized when getting the total property that the first time when GetListCart is being called the value is null and the second time, when the label text is set it returns the correct value. Why is this happening?

Binding in generic control is null

I have several generic buttons. Both title and the corresponding icon are displayed correctly, but the tap function does not work.
HomePage.xaml with the ScanningApp control
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="primetals.ScannerApp.Views.HomePage"
xmlns:controls="clr-namespace:primetals.ScannerApp.Controls"
xmlns:resource="clr-namespace:primetals.ScannerApp"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
BackgroundColor="White"
x:Name="self"
Title="{Binding Title}">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="controls:ScanningApp">
<Setter Property="WidthRequest" Value="220"></Setter>
<Setter Property="HeightRequest" Value="220"></Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="3*"></RowDefinition>
<RowDefinition Height="3*"></RowDefinition>
<RowDefinition x:Name="backgroundImageRow" Height="4*"></RowDefinition>
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" HorizontalOptions="CenterAndExpand" Margin="0,10,0,10">
<!-- Application Logo -->
<Image Source="icon_scannerapp.png" WidthRequest="96" HeightRequest="96"></Image>
<!-- Welcome Text -->
<Label Text="{x:Static resource:ApplicationResources.WelcomeMessageLine1}" FontSize="Large">
</Label>
<Label FontSize="Large">
<Label.FormattedText>
<FormattedString>
<Span Text="{x:Static resource:ApplicationResources.WelcomeMessageLine2}"></Span>
<Span Text="{x:Static resource:ApplicationResources.WelcomeMessageSpareParts}" FontAttributes="Bold" FontSize="Large"></Span>
<Span Text="{x:Static resource:ApplicationResources.WelcomeMessageOr}"></Span>
<Span Text="{x:Static resource:ApplicationResources.WelcomeMessageSensorData}" FontAttributes="Bold" FontSize="Large"></Span>
<Span Text="!"></Span>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
<!-- Scanning Applications -->
<StackLayout Orientation="Horizontal" Grid.Row="1" BindableLayout.ItemsSource="{Binding Apps}" HorizontalOptions="Center" VerticalOptions="Start">
<BindableLayout.ItemTemplate>
<DataTemplate>
<controls:ScanningApp Margin="0,0,5,0"
ImageSource="{Binding ImageUrl}"
TapImageSource="{Binding TapImageUrl}"
Text="{Binding Title}"
TappedCommand="{Binding BindingContext.AppTappedCommand, Source={x:Reference self}}"
TappedCommandParameter="{Binding}">
</controls:ScanningApp>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
<!-- Background Image -->
<Image x:Name="backgroundImage" Grid.Row="2" Source="background_scannerapp_PT.jpg" Aspect="AspectFit" HorizontalOptions="Fill" VerticalOptions="Fill"></Image>
</Grid>
</ContentPage>
HomepageViewModel.cs:
AppTappedCommand is set correctly
this.AppTappedCommand = new DelegateCommand<ScanApplication>((app) => OnGotoScanPage(app));
this.Title = ApplicationResources.ApplicationTitleCaption;
public async void OnGotoScanPage(ScanApplication app)
{
NavigationParameters parameters = new NavigationParameters();
parameters.Add(Constants.Parameters.App, app.AppId);
await this.NavigationService.NavigateAsync($"{nameof(ScanPage)}", parameters);
}
ScanningApp.xaml.cs:
After Clicking the button TappedCommand is null.
public static readonly BindableProperty TappedCommandProperty = BindableProperty.Create(nameof(TappedCommand), typeof(ICommand), typeof(ScanningApp), default(ICommand), Xamarin.Forms.BindingMode.OneWay);
public ICommand TappedCommand
{
get
{
return (ICommand)GetValue(TappedCommandProperty);
}
set
{
SetValue(TappedCommandProperty, value);
}
}
public static readonly BindableProperty TappedCommandParameterProperty = BindableProperty.Create(nameof(TappedCommandParameter), typeof(object), typeof(ScanningApp), null, Xamarin.Forms.BindingMode.OneWay);
public object TappedCommandParameter
{
get
{
return GetValue(TappedCommandParameterProperty);
}
set
{
SetValue(TappedCommandParameterProperty, value);
}
}
private bool OnExecuteTap()
{
img.Source = this.ImageSource;
if (this.TappedCommand != null && this.TappedCommand.CanExecute(this.TappedCommandParameter))
{
this.TappedCommand.Execute(this.TappedCommandParameter);
}
return false;
}
ScanningApp.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="primetals.ScannerApp.Controls.ScanningApp"
x:Name="self">
<Grid Padding="1" BackgroundColor="{StaticResource PrimetalsLightGrayColor}">
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
</Grid.GestureRecognizers>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="1*" ></RowDefinition>
</Grid.RowDefinitions>
<Image x:Name="img" Grid.Row="0" Source="{Binding ImageSource, Source={x:Reference self}}" Aspect="AspectFit" VerticalOptions="CenterAndExpand"
Margin="20"></Image>
<Label Grid.Row="1" Text="{Binding Text, Source={x:Reference self}}"
Margin="10,0,10,10"
FontSize="Medium" TextColor="{StaticResource PrimetalsAccentColor}"
VerticalTextAlignment="Center" HorizontalTextAlignment="Center"></Label>
</Grid>
</Grid>
</ContentView>
Originally this sourcecode worked (about one year ago) (but there may be problems with new packages in VS). I hope you can help me. Thanks a lot!
br
It seems that there should be a TapGestureRecognizer_Tapped event handler in ScanningApp.xaml.cs from your code.
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
So you could do like :
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
img.Source = this.ImageSource;
if (this.TappedCommand != null && this.TappedCommand.CanExecute(this.TappedCommandParameter))
{
this.TappedCommand.Execute(this.TappedCommandParameter);
}
}

Xamarin : Adding multiple bindings to multiple collection views on the same page

I am currently trying to build two separate collection views on the same page in Xamarin. I keep getting the error that content is set more than once and also that I've set the content binding more than once. How do I add different bindings to two separate collection views on the same page?
ConsumerOrders.xaml page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewmodels="clr-namespace:Shared.ViewModel"
mc:Ignorable="d"
x:Class="Shared.consumerOrders">
<ContentPage.BindingContext>
<viewmodels:AddedServicesViewModel />
</ContentPage.BindingContext>
<d:ContentPage.BindingContext>
<viewmodels:PastOrderViewModel />
</d:ContentPage.BindingContext>
<ScrollView>
<CollectionView ItemsSource="{Binding ViewAddedServices}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="4"/>
<!--0-->
<RowDefinition Height="30"/>
<!--1-->
<RowDefinition Height="20"/>
<!--2-->
<RowDefinition Height=".25"/>
<!--3-->
<RowDefinition Height="4"/>
<!--4-->
<RowDefinition Height="Auto"/>
<!--5-->
<RowDefinition Height="Auto"/>
<!--6-->
<RowDefinition Height=".25"/>
<!--7-->
<RowDefinition Height="Auto"/>
<!--8-->
<RowDefinition Height="Auto"/>
<!--9-->
<RowDefinition Height=".25"/>
<!--10-->
<RowDefinition Height="Auto"/>
<!--11-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="4"/>
</Grid.ColumnDefinitions>
<Label Text="Services added" FontAttributes="Bold" TextColor="#F65506" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" VerticalTextAlignment="End" HorizontalTextAlignment="Start" FontSize="18"/>
<Label Grid.Column="1" Grid.Row="7" BackgroundColor="#707070" Grid.ColumnSpan="3"/>
<!--This is a line-->
<BoxView BackgroundColor="#F0F0F0" Grid.Row="9" Grid.Column="1" Grid.ColumnSpan="3" CornerRadius="22"/>
<Label Grid.Column="1" Grid.Row="9" Padding="10" TextColor="Black" FontSize="18" Text="{Binding BusinessName}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" Grid.ColumnSpan="2"/>
<Label Grid.Column="3" Grid.Row="9" Padding="0,0,20,0" TextColor="#F65506" FontAttributes="Bold" FontSize="18" Text="View" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand" Grid.ColumnSpan="2"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView ItemsSource="{Binding ViewQuoteStatus}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="4"/>
<!--0-->
<RowDefinition Height="30"/>
<!--1-->
<RowDefinition Height="20"/>
<!--2-->
<RowDefinition Height=".25"/>
<!--3-->
<RowDefinition Height="4"/>
<!--4-->
<RowDefinition Height="Auto"/>
<!--5-->
<RowDefinition Height="Auto"/>
<!--6-->
<RowDefinition Height=".25"/>
<!--7-->
<RowDefinition Height="Auto"/>
<!--8-->
<RowDefinition Height="Auto"/>
<!--9-->
<RowDefinition Height=".25"/>
<!--10-->
<RowDefinition Height="Auto"/>
<!--11-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="4"/>
</Grid.ColumnDefinitions>
<Label Text="Past Orderrs" FontAttributes="Bold" TextColor="#F65506" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" VerticalTextAlignment="End" HorizontalTextAlignment="Start" FontSize="18"/>
<Label Grid.Column="1" Grid.Row="7" BackgroundColor="#707070" Grid.ColumnSpan="3"/>
<!--This is a line-->
<BoxView BackgroundColor="#F0F0F0" Grid.Row="9" Grid.Column="1" Grid.ColumnSpan="3" CornerRadius="22"/>
<Label Grid.Column="1" Grid.Row="9" Padding="10" TextColor="Black" FontSize="18" Text="{Binding BusinessName}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" Grid.ColumnSpan="2"/>
<Label Grid.Column="3" Grid.Row="9" Padding="0,0,20,0" TextColor="#F65506" FontAttributes="Bold" FontSize="18" Text="View" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand" Grid.ColumnSpan="2"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ScrollView>
</ContentPage>
AddedServicesViewModel.cs :
using Shared.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace Shared.ViewModel
{
class AddedServicesViewModel
{
readonly IList<AddedServiceStatus> source;
public ObservableCollection<AddedServiceStatus> ViewAddedServices { get; private set; }
public AddedServicesViewModel()
{
source = new List<AddedServiceStatus>();
CreateAddedServicesCollection();
}
void CreateAddedServicesCollection()
{
source.Add(new AddedServiceStatus
{
BusinessName = "Duck's Duct Cleaning"
});
source.Add(new AddedServiceStatus
{
BusinessName = "Rodney's Home Repair"
});
ViewAddedServices = new ObservableCollection<AddedServiceStatus>(source);
}
}
}
PastOrderViewModel :
using Shared.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace Shared.ViewModel
{
class PastOrderViewModel
{
readonly IList<PastOrderStatus> source;
public ObservableCollection<PastOrderStatus> ViewPastOrders { get; private set; }
public PastOrderViewModel()
{
source = new List<PastOrderStatus>();
CreatePastOrderCollection();
}
void CreatePastOrderCollection()
{
source.Add(new PastOrderStatus
{
BusinessName = "Karen's Magnificent Dog Grooming"
});
source.Add(new PastOrderStatus
{
BusinessName = "Harry's In Home Haircuts"
});
source.Add(new PastOrderStatus
{
BusinessName = "Shelly's Floral Arrangements"
});
ViewPastOrders = new ObservableCollection<PastOrderStatus>(source);
}
}
}
You could also bind a ViewModel to each CollectionView separately.
like:
<CollectionView ItemsSource="{Binding ViewAddedServices}">
<CollectionView.BindingContext>
<viewmodels:AddedServicesViewModel/>
</CollectionView.BindingContext>
...
</CollectionView>
<CollectionView ItemsSource="{Binding ViewPastOrders}">
<CollectionView.BindingContext>
<viewmodels:PastOrderViewModel/>
</CollectionView.BindingContext>
...
</CollectionView>
You can't have two ViewModels binding to a SingleView. (as far a I know)
I see that the DataTemplate in both Collections are the same..... there are many ways to refactor....
You could create two CustomView one with the AddedServicesViewModel and the other with PastOrderViewModel
You can merge the two ViewModels into one, and create a CustomView that it's the collection.
Another thing that I see that It could not work is that you can't have a more than one View Nested in a ScrollView
<ScrollView>
<StackLayout> /* Or any other Layout, Grid, Absolute, Flex etc... */
</StackLayout>
</ScrollView>
Another thing is that a CollectionView with orientation vertical in a ScrollView maybe it won't behave as you expect, since the CollectionView with orientation vertical it has Scroll
Two CollectionViews with orientation vertical in the same View it should have a Height, I would do something like this
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<CollectionView Grid.Row="0" ItemsSource="{Binding ViewQuoteStatus}"> ... </CollectionView>
<CollectionView Grid.Row="1" ItemsSource="{Binding ViewAddedServices}"> ... </CollectionView>
</Grid>
or if you create a custom view (custom control)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<MyCustomCollectionView Grid.Row="0" ItemsSource="{Binding ViewQuoteStatus}"> ... </MyCustomCollectionView>
<MyCustomCollectionView Grid.Row="1" ItemsSource="{Binding ViewAddedServices}"> ... </MyCustomCollectionView>
</Grid>

ListView throws UnhandledException when ScrollTo

I have a simple page with a ListView like this
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListViewDemo.MainPage">
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="From" />
<DatePicker x:Name="fromPicker" Grid.Row="1" />
<Label Text="To" Grid.Column="1" />
<DatePicker x:Name="toPicker" Grid.Column="1" Grid.Row="1" />
</Grid>
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding FromDate}" />
<Label Text="{Binding ToDate}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
When the Date is changed I want to scroll to the Event, that is closest to the current Date, but I get an UnhandledException when I use ScrollTo on UWP, and iOS just do not scroll.
I was thinking of using ItemAppearing, but is it trustable, if I have enough events on the list?
If I use await Task.Delay(500) I do not get the UnhandledException, but instead the content jumps on my screen.
Is there any solution to this problem?
public void SetEvents(params CalenderEventDto[] events)
{
var dateToScrollTo = DateTime.Now.Date;
var scrollToEvent = events?.OrderBy(x => x.Start.Date)?.FirstOrDefault(c => c.Start.Date >= dateToScrollTo || c.End.Date >= dateToScrollTo );
var orderedEvents = events.GroupBy(x => x.Start.Date).OrderBy(x => x.Key);
_calendarEvents.Clear();
foreach (var groupedEvents in orderedEvents)
{
foreach (var calendarEvent in groupedEvents)
{
_calendarEvents.Add(calendarEvent);
}
}
//await Task.Delay(450);
Device.BeginInvokeOnMainThread(() => lstCalendar.ScrollTo(scrollToEvent, ScrollToPosition.Start, false));
}
EDIT
I figured out, the problem is on iOS too
I figured out, if I moved the SetEvents from the constructor to OnAppearing it works

Categories