Ui is not updating on realtime - xaml

I have a listview for displaying all the items that i getting from api.i have a live event which will modify one field inside the item of type observablecollection
<?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="Dyocense.Views.ManageJobs"
Title="All jobs">
<ContentPage.ToolbarItems>
<ToolbarItem Text="ADD" Clicked="AddJob"></ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<SearchBar x:Name="Search" SearchButtonPressed="SearchBar_SearchButtonPressed"></SearchBar>
<ListView x:Name="JobsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
CachingStrategy="RecycleElement"
ItemAppearing="BrowseJobList_ItemAppearing"
IsPullToRefreshEnabled="true"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Frame HasShadow="True" >
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}"
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
FontSize="Medium"
FontAttributes="Bold"/>
<Label Text="Status"
Grid.Row="1" Grid.Column="0"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding Status}"
Grid.Row="1" Grid.Column="1"
FontSize="16"/>
<Label Text="Goal"
Grid.Row="2" Grid.Column="1"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding Goal}"
Grid.Row="2" Grid.Column="2"
FontSize="16" />
<Label Text="Part"
Grid.Row="3" Grid.Column="1"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding PartName}"
Grid.Row="3" Grid.Column="2"
FontSize="16" />
<Label Text="Assembly"
Grid.Row="4" Grid.Column="1"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding NodeName}"
Grid.Row="4" Grid.Column="2"
FontSize="16" />
<Label Text="GoodCount"
Grid.Row="5" Grid.Column="0"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding GoodCount}"
Grid.Row="6" Grid.Column="0"
FontSize="16"
HorizontalTextAlignment="Center"/>
<Label Text="RejectCount"
Grid.Row="5" Grid.Column="1"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding RejectCount}"
Grid.Row="6" Grid.Column="1"
FontSize="16"
HorizontalTextAlignment="Center"/>
<Label Text="DownTimeCount"
Grid.Row="5" Grid.Column="2"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding DownTimeCount}"
Grid.Row="6" Grid.Column="2"
FontSize="16"
HorizontalTextAlignment="Center"/>
</Grid>
</StackLayout>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Grid Padding="6" IsVisible="{Binding IsBusy}">
<!--set the footer to have a zero height when invisible-->
<Grid.Triggers>
<Trigger TargetType="Grid" Property="IsVisible" Value="False">
<Setter Property="HeightRequest" Value="0" />
</Trigger>
</Grid.Triggers>
<!--the loading content-->
<Label Text="Loading..." VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
</ListView.Footer>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
i want to update the good count on real time. i debugged the code its getting updated in my list but only updating the UI on a user scroll. Here is my viewmodel
public class JobViewModel: INotifyPropertyChanged
{
private ObservableCollection<Job> items;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Job> Items
{
get { return items; }
set
{
items = value;
if (items != value)
{
items = value;
OnPropertyChanged(nameof(Items));
}
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
private void updateJoblistOnEvent(NotificationEntity message)
{
var jobId = message.JobId;
Job job = Items.FirstOrDefault(a => a.JobId.Equals(jobId));
switch (message.EventCode)
{
case MessageTypeEnum.Pulse: //Pulse
job.GoodCount = job.GoodCount + 1;
//job.Status = 'Running';
break;
default:
break;
}
}
i am suspecting two things
CachingStrategy="RecycleElement" i removed this one that its not updating with scroll also
any problem with INotifyPropertyChanged, i tried to remove one item from list its working and updating the ui.i want to update the field inside the item
can any one help me

As deduced from the comments, you need to also implement the INotifyPropertyChanged interface on the Job object. Using the ObservableCollection only helps for changes in that collection, so when you remove or add a Job object, not if something changes inside the Job object.
So, in your Job object do this (code reverse engineered from what you posted):
public class Job : INotifyPropertyChanged
{
private int goodCount;
public int GoodCount
{
get { return goodCount; }
set
{
if (goodCount != value)
{
goodCount = value;
OnPropertyChanged(nameof(GoodCount));
}
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
You could remove the INotifyPropertyChanged from your JobViewModel, but you probably need it there at some point as well

Related

Using DataTrigger to change colour of ListView depending on value returned in ItemSource

I have a XAML page with a listview. What I want to do is when the value of the first column "NumType" equals "S" the background colour for that row is set to a different colour.
I have been looking at using DataTriggers, but I'm not sure if this is the way to go.
Below is the code that I currently have.
?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MobileWarehouseXamarin.Controls"
xmlns:ef="clr-namespace:MobileWarehouseXamarin.Effects"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="MobileWarehouseXamarin.Controls.MW_AdjustmentsAwaiting_0"
xmlns:vm="clr-namespace:MobileWarehouseXamarin.ViewModels;assembly=MobileWarehouseXamarin"
x:Name="this"
RowSpacing="0"
ColumnSpacing="0"
Padding="5,0,5,0">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="80"/>
<!--<ColumnDefinition Width="300"/>-->
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text="Location" Style="{StaticResource KeyValueSmall_Key}" />
<Label Grid.Column="1" Text="Barcode" Style="{StaticResource KeyValueSmall_Key}" />
<Label Grid.Column="2" Text="User" Style="{StaticResource KeyValueSmall_Key}" />
<Label Grid.Column="3" Text="Date" Style="{StaticResource KeyValueSmall_Key}" />
<!--<TextBlock Grid.Column="4" Text="Reason" Style="{StaticResource TextBlockLabel}" />-->
</Grid>
<ListView Grid.Row="1" x:Name="gridViewAwaitingAdjustmentDetails" ItemsSource="{Binding AwaitingAdjustment}" SelectedItem="{Binding SelectedAdjustment, Mode=TwoWay}" >
<!--Style="{StaticResource ListViewItemHighlighted}">-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="80"/>
<!--<ColumnDefinition Width="300" />-->
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding NumType}" Style="{StaticResource KeyValueSmall_Value}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="0" Text="{Binding LocationCode}" Style="{StaticResource KeyValueSmall_Value}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Text="{Binding Barcode}" Style="{StaticResource KeyValueSmall_Value}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="2" Text="{Binding UserName}" Style="{StaticResource KeyValueSmall_Value}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="2" Text="{Binding PickingAdjustementDate}" Style="{StaticResource KeyValueSmall_Value}" Margin="0,0,0,0" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Any thoughts or suggestions would be very much appreciated
I have looked at using the DataTrigger, but not sure how to go about it or would I be better off looking at Template Selectors?
There are several ways to achieve this.
A simple method is to add a field to the item of your ListView and bind it to the BackgroundColor of the item, for example:
public Color BgColor { get; set; } = Color.Yellow;
I created a simple demo and achieved this function,you can refer to the following code:
Item.cs
public class Item: INotifyPropertyChanged
{
public Color BgColor { get; set; } = Color.Yellow;
private string _numType;
public string NumType
{
get => _numType;
set
{
SetProperty(ref _numType, value);
setBgColor();// set BgColor
}
}
private void setBgColor()
{
if (NumType != null && NumType.Equals("S")) {
BgColor = Color.Green;
}
}
public string LocationCode { get; set; }
public string Barcode { get; set; }
public string UserName { get; set; }
public string PickingAdjustementDate { get; set; }
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
MyViewModel.cs
public class MyViewModel
{
public ObservableCollection<Item> Items { get; set; }
public MyViewModel() {
Items = new ObservableCollection<Item>();
Items.Add( new Item { NumType = "S" , LocationCode = "0001"});
Items.Add(new Item { NumType = "M", LocationCode = "0002" });
Items.Add(new Item { NumType = "L", LocationCode = "0003" });
}
}
MainPage.xaml
<?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:xamlistviewapp131="clr-namespace:XamListViewApp131"
x:Class="XamListViewApp131.MainPage">
<ContentPage.BindingContext>
<xamlistviewapp131:MyViewModel></xamlistviewapp131:MyViewModel>
</ContentPage.BindingContext>
<StackLayout>
<ListView Grid.Row="1" x:Name="gridViewAwaitingAdjustmentDetails" ItemsSource="{Binding Items}" >
<!--Style="{StaticResource ListViewItemHighlighted}">-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="{Binding BgColor}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="80"/>
<!--<ColumnDefinition Width="300" />-->
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding NumType}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="0" Text="{Binding LocationCode}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Text="{Binding Barcode}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="2" Text="{Binding UserName}" Margin="0,0,0,0" />
<Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="2" Text="{Binding PickingAdjustementDate}" Margin="0,0,0,0" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>

First-time user onboarding with Xamarin.Forms

I am implementing a first-time user onboarding in a Xamarin.Forms application like the one on the image below:
Please, how can I quickly do that?
Thank you in advance.
Do you want to achieve the result like following GIF?
You can use CarouselView and IndicatorView to achieve it.
Here is layout code.I dont adjust the layout like yours, you can adjust it by yourself, If you want to make Next and Skip Button over float the CarouselView, you can use AbsoluteLayout
<StackLayout Margin="10">
<CarouselView x:Name="myCarouselView" ItemsSource="{Binding Monkeys}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="50"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Skip" Grid.Column="0" BackgroundColor="Transparent" Clicked="Button_Clicked"></Button>
<Button Text="Next" Grid.Column="1" BackgroundColor="Transparent" Clicked="Button_Clicked_1"></Button>
</Grid>
<IndicatorView x:Name="indicatorView"
MaximumVisible="6"
Margin="0,0,0,40"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" />
</StackLayout>
Here is layout bakground code.
public partial class BasicIndicatorViewPage : ContentPage
{
int monkeyCount;
public BasicIndicatorViewPage()
{
InitializeComponent();
MonkeysViewModel monkeysViewModel= new MonkeysViewModel();
monkeyCount = monkeysViewModel.Monkeys.Count;
BindingContext = monkeysViewModel;
}
private void Button_Clicked(object sender, System.EventArgs e)
{
Navigation.PushAsync(new Page1());
Navigation.RemovePage(this);
}
private void Button_Clicked_1(object sender, System.EventArgs e)
{
if (myCarouselView.Position < monkeyCount-1)
{
myCarouselView.Position += 1;
}
else
{
Navigation.PushAsync(new Page1());
Navigation.RemovePage(this);
}
}
}
Here is my demo, you can download it.
https://github.com/851265601/XFormsCarouselView-IndicatorViewLoginPage
If you want to put the indicatorView and Button in the same line like this screenshot.
You can use this layout(indicatorView to the Grid).
<StackLayout Margin="10">
<CarouselView x:Name="myCarouselView" ItemsSource="{Binding Monkeys}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="50"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Skip" Grid.Column="0" BackgroundColor="Transparent" Clicked="Button_Clicked"></Button>
<IndicatorView x:Name="indicatorView"
MaximumVisible="6"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" Grid.Column="1" />
<Button Text="Next" Grid.Column="2" BackgroundColor="Transparent" Clicked="Button_Clicked_1"></Button>
</Grid>
</StackLayout>
You could use the offical Xamarin.Forms CarouselView but that's still in preview. You could also potentially look at the Sharpnado's solution with HorizontalListView. Your third option would be to use Alex Rainman's CarouselView.

Xamarin Forms Carousel view issue with binding

Hello I’m having an issue with binding a list of string to my Carousel View
First I have a list of an object I get from my server
public class PostObject
{
public string PostOwner { get; set; }
public string Id { get; set; }
public string Post { get; set; }
public string ProfileImage { get; set; }
public List<string> PostImages { get; set; }
}
List<PostObject> posts = new List<PostObject>();
This works as I expected.
Next I have a card view I created and within the card view I want to have a Carousel View.
So I have setup my Xaml like this (omitting the parts that works for clarity)
<?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:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
NavigationPage.HasNavigationBar="True"
NavigationPage.HasBackButton="False"
NavigationPage.BackButtonTitle="Back"
Title="amici"
x:Class="amici.Posts">
<NavigationPage.TitleView>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" Spacing="10" >
<Label x:Name="GroupTitle" TextColor="White" FontSize="Medium"/>
</StackLayout>
</NavigationPage.TitleView>
<ContentPage.ToolbarItems>
<ToolbarItem Name="iconexample" Icon="settings.png" Priority="0" Order="Primary" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView x:Name="ItemsListView"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement">
<!--ItemSelected="OnItemSelected"-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Padding="10">
<Frame x:Name="myframe" HasShadow="True" >
<Grid HorizontalOptions="FillAndExpand" RowSpacing="0" ColumnSpacing="0" >
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Text="{Binding PostOwner}" LineBreakMode="WordWrap" Font="Bold,16" />
<controls:CircleImage Grid.Row="0" Margin="10" BorderColor="white" BorderThickness="1" VerticalOptions="Start" HorizontalOptions="Start" Source="{Binding ProfileImage}" Aspect="AspectFit">
<controls:CircleImage.WidthRequest>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="Android, iOS">65</On>
</OnPlatform>
</controls:CircleImage.WidthRequest>
<controls:CircleImage.HeightRequest>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="Android, iOS">65</On>
</OnPlatform>
</controls:CircleImage.HeightRequest>
</controls:CircleImage>
<Label Grid.Row="1" Text="{Binding Post}" LineBreakMode="WordWrap" Font="Bold,16" />
<CarouselView x:Name="PostImages" Grid.Row="2" ItemsSource="{Binding PostImages}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding .}" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<!--<Image Grid.Row="2" Source="{Binding ImageURL}" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />-->
<BoxView Grid.Row="3" BackgroundColor="black" HeightRequest="1" HorizontalOptions="FillAndExpand"/>
<StackLayout Grid.Row="4" Orientation="Horizontal" >
<Label Text="Likes: " LineBreakMode="NoWrap" Font="Bold,14" />
<Label Text="0" LineBreakMode="NoWrap" FontSize="14" />
</StackLayout>
<StackLayout Grid.Row="5" Orientation="Horizontal" >
<Label Text="Comments: " LineBreakMode="NoWrap" Font="Bold,14" HorizontalOptions="End" />
<Label Text="0" HorizontalOptions="End" LineBreakMode="NoWrap" FontSize="14" />
</StackLayout>
<!--<Label Grid.Row="2" Text="{Binding OwnerFullName}" LineBreakMode="NoWrap" FontSize="16" />-->
</Grid>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
In my code behind I have this
public Posts (GroupInfo ginfo)
{
InitializeComponent ();
GroupTitle.Text = ginfo.Title;
CurrentGroupInfo = ginfo;
GetDataPosts();
ItemsListView.RefreshCommand = new Command(() => {
GetDataPosts();
ItemsListView.IsRefreshing = false;
});
}
public void GetDataPosts()
{
try
{
string apikey = Application.Current.Properties["api"].ToString();
ItemsListView.ItemsSource = null;
posts.Clear();
if (RestController.GetMyPostData(ref posts, CurrentGroupInfo.Id.ToString(), apikey))
{
ItemsListView.ItemsSource = posts;
}
}
catch(Exception e)
{
Debug.WriteLine(e.Message);
}
}
now up to this point everything works and no errors but when the app goes to render the page I get a error
System.TypeInitializationException: The type initializer for 'Xamarin.Forms.ItemsView' threw an exception.
which I trace back to the Carousel View. When I comment out the Carousel View the it works. so I'm thinking I can't bind OR use the Carousel View in the way I thought?
The CarouselView used to be a plugin that has now become part of Xamarin.Forms effective with version 4. You can use an earlier XF version but you will need to get this plugin, add assembly references to your XAML and put initialization code in your platform specific projects.
Alternatively, you could upgrade to Xamarin.Forms 4
Even though you can see the Carousel View on Xamarin.Forms 3.6.0.344457, it only defines an interface there. There're no implementations and properties in the Carousel View Class.
You can only utilize it under Xamarin.Forms 4.0. As it is still a preview version now, there're some limitations. See my post here: https://stackoverflow.com/a/56235795/8354952 for more information.

Nested List view in Xamarin forms xaml with MVVM

I want nested list view like below in xamarin forms
I am using XAML and wants to bind using MVVM
My model as below
public class LineItemTaxDto
{
public int InvoiceLineItemId { get; set; }
public int InvoiceId { get; set; }
public int TaxId { get; set; }
public decimal TaxRate { get; set; }
public decimal TaxAmount { get; set; }
public string TaxName { get; set; }
public ObservableCollection<LineItemTaxDto> SubTaxes { get; set; }
}
In this Group tax is my main taxname and it contains sub taxes (VAT, GST).
EDIT
My xaml code is below
<ListView x:Name="TaxListView" ItemsSource="{Binding Invoice.Taxgroup}" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" SeparatorVisibility="None" HasUnevenRows="false" RowHeight="35">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Orientation="Horizontal" Spacing="0" HorizontalOptions="End">
<Label Text="{Binding Source={x:Reference TaxListView}, Path=BindingContext.CurrentOutlet.ReceiptTemplate.TaxLable, StringFormat='{0} ('}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
<Label Text="{Binding TaxName, StringFormat='{0})'}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
</StackLayout>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
<ListView x:Name="TaxListView2" ItemsSource="{Binding Invoice.Taxgroup}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" SeparatorVisibility="None" HasUnevenRows="false" RowHeight="35">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Orientation="Horizontal" Spacing="0" HorizontalOptions="End">
<Label Text="{Binding TaxName}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
</StackLayout>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
But is not working. please help me to what I am going wrong. Thanks in advance
Solved
I solve above result using single list no need to nested list view.
My code as below.
My xaml code look like:
<ListView
x:Name="TaxListView"
ItemsSource="{Binding Invoice.ReceiptTaxList}"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
SeparatorVisibility="None"
HasUnevenRows="false"
RowHeight="35"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding TaxName}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
My view model code look like:
var TMPTaxList = invoice.InvoiceLineItems.Where(x => x.TaxId > 1).Select(x =>
{
return new KeyValuePair<LineItemTaxDto, ObservableCollection<LineItemTaxDto>>(new LineItemTaxDto()
{
InvoiceLineItemId = x.Id,
InvoiceId = x.InvoiceId,
TaxId = x.TaxId,
TaxRate = x.TaxRate,
TaxAmount = x.TaxAmount,
TaxName = "Tax (" + x.TaxName + ")"
}, x.LineItemTaxes);
});
var taxes = new ObservableCollection<LineItemTaxDto>();
foreach (var tax in TMPTaxList.GroupBy(tax => tax.Key.TaxId)
.Select(grp => grp.First()))
{
taxes.Add(tax.Key);
foreach (var subtax in tax.Value.Where(x => x.TaxId > 0))
{
taxes.Add(subtax);
}
}
invoice.ReceiptTaxList = taxes;

How to concatenate strings in Xamarin.Forms?

I want my two strings to be diplayed on just a single line. Is it possible for it to appear like this:
Curry Stephen
using this code
Text="{Binding EMP_LAST_NAME + EMP_FIRST_NAME}" ? ? ?
I currently have this code. Thanks a lot.
<ListView ItemsSource="{Binding EmployeesList}"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10" RowSpacing="10" ColumnSpacing="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<controls:CircleImage Source="icon.png"
HeightRequest="66"
HorizontalOptions="CenterAndExpand"
Aspect="AspectFill"
WidthRequest="66"
Grid.RowSpan="2"
/>
<Label Grid.Column="1"
Grid.Row="1"
Text="{Binding EMP_LAST_NAME}"
TextColor="White"
FontSize="18"
Opacity="0.6"/>
<Label Grid.Column="1"
Grid.Row="1"
Text="{Binding EMP_FIRST_NAME}"
TextColor="White"
FontSize="18"
Opacity="0.6"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
You can't bind to multiple properties on a View Element.
In this case you should create a new property which does the format you want and bind it to the View.
Example:
public class EmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
Then in XAML:
<Label Text="{Binding FullName}"/>
Another approach:
As suggested in the comments we can also use FormattedText property in a Label:
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding FirstName}" />
<Span Text="{Binding LastName}"/>
</FormattedString>
</Label.FormattedText>
Use FormattedText property in xamarin forms Label as follow:
<Label Grid.Column="1" Grid.Row="1">
<Label.FormattedText>
<FormattedString>
<Span TextColor="White" FontSize="18" Text="{Binding EMP_LAST_NAME'}"/>
<Span TextColor="White" FontSize="18" Text="{Binding EMP_FIRST_NAME}"/>
</FormattedString>
</Label.FormattedText>
</Label>
Xamarin.Forms Label
And also you can add Style to avoid code duplication for TextColor, FontSize and other properties in your code.
Styling Xamarin.Forms Apps using XAML Styles
<Label Text="{Binding Value, StringFormat='string before value {0:F0} string after value'}"/>
Suppose your value is 1234.
The output will be in this case:
string before value 1234 string after value
You could use IValueConverter, which will accept Employee and will return full name.
Or you could use MultiComponentLabel. It allows you to bind couple different values to one Label.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Name="Page"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:SuperForms.Controls;assembly=SuperForms.Controls"
x:Class="SuperForms.Samples.MultiComponentLabelPage">
<controls:MultiComponentLabel Margin="0,20,0,0">
<controls:MultiComponentLabel.Components>
<controls:TextComponent Text="{Binding EMP_LAST_NAME}"/>
<controls:TextComponent Text="{Binding EMP_FIRST_NAME}"/>
</controls:MultiComponentLabel.Components>
</controls:MultiComponentLabel>
</ContentPage>
Just use MultiComponentLabel instead of couple Labels
For your ListView
<ListView ItemsSource="{Binding EmployeesList}"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10" RowSpacing="10" ColumnSpacing="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<controls:CircleImage Source="icon.png"
HeightRequest="66"
HorizontalOptions="CenterAndExpand"
Aspect="AspectFill"
WidthRequest="66"
Grid.RowSpan="2" />
<controls:MultiComponentLabel Grid.Row="1" Grid.Column="1">
<controls:MultiComponentLabel.Components>
<controls:TextComponent Text="{Binding EMP_LAST_NAME}"/>
<controls:TextComponent Text="{Binding EMP_FIRST_NAME}"/>
</controls:MultiComponentLabel.Components>
</controls:MultiComponentLabel>
</Grid>
</ViewCell>
Xamarin Forms 4.7 add support for Multibinding which can be used like this:
<Label>
<Label.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName" />
<Binding Path="LastName" />
</MultiBinding>
</Label.Text>
</Label>
In the example provided, "FirstName" and "LastName" are regular viewmodel properties defined in the class:
public string FirstName { get; set; }
public string LastName { get; set; }