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

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>

Related

Define listview in resource file which can be used in different places with same model

I have created the following ListView to display data
<dataControls:RadListView x:Name="ItemsListView"
ItemsSource="{Binding StudyResults,Mode=TwoWay}"
MinimumHeightRequest="70"
HeightRequest="{Binding Height}"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
<dataControls:RadListView.ItemTemplate>
<DataTemplate>
<listView:ListViewTemplateCell>
<listView:ListViewTemplateCell.View>
<Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
<StackLayout Padding="5,1,1,5" Grid.Column="0">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
</Grid>
<StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
<Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
</StackLayout>
</StackLayout>
</Grid>
</listView:ListViewTemplateCell.View>
</listView:ListViewTemplateCell>
</DataTemplate>
</dataControls:RadListView.ItemTemplate>
</dataControls:RadListView>
I want to reuse this exact same ListView + markup in a other screens/view, just with a different ItemsSource it will be bound to same model. I need to use different item source in different screens.
Is there a better way to create some type of resource so I can reuse this?
As lvan's opinion, you can set DataTemplate in ContentPage.Resource or ResourceDictionary, Some code like this:
<ContentPage.Resources>
<DataTemplate x:Key="Radtemplate">
<listView:ListViewTemplateCell>
<listView:ListViewTemplateCell.View>
<Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
<StackLayout Padding="5,1,1,5" Grid.Column="0">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
</Grid>
<StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
<Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
</StackLayout>
</StackLayout>
</Grid>
</listView:ListViewTemplateCell.View>
</listView:ListViewTemplateCell>
</DataTemplate>
</ContentPage.Resources>
<StackLayout>
<!-- Place new controls here -->
<dataControls:RadListView x:Name="ItemsListView" ItemTemplate="{StaticResource Radtemplate}"
ItemsSource="{Binding StudyResults,Mode=TwoWay}"
MinimumHeightRequest="70"
HeightRequest="{Binding Height}"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
</dataControls:RadListView>
</StackLayout>
About DateTemplate detailed info, you can take a look the following article:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/creating
Update:
Because RadListView is the third party control, I can not install it, so I use ListView as an example, it is the same, you can take a look how to use TapGestureRecognizer.
Please give the Page an x:name=listviewpage firstly, then
<ContentPage
x:Class="demo3.listviewsample.Page2"
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"
x:Name="listviewpage"
mc:Ignorable="d">
<ContentPage.Resources>
<DataTemplate x:Key="datatemplate1">
<ViewCell>
<StackLayout Margin="5" VerticalOptions="FillAndExpand">
<BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
<Label Text="{Binding username}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.command, Source={x:Reference listviewpage}}" CommandParameter="{Binding Email}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<ListView
HasUnevenRows="True"
ItemTemplate="{StaticResource datatemplate1}"
ItemsSource="{Binding models}" />
</StackLayout>
</ContentPage.Content>
Or you can give ViewCell an x:Name viewcell1 firstly, then:
<ContentPage.Resources>
<DataTemplate x:Key="datatemplate1">
<ViewCell x:Name="viewcell">
<StackLayout Margin="5" VerticalOptions="FillAndExpand">
<BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
<Label Text="{Binding username}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Parent.BindingContext.command, Source={x:Reference viewcell}}" CommandParameter="{Binding Email}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ContentPage.Resources>
public partial class Page2 : ContentPage
{
public ObservableCollection<model3> models { get; set; }
public RelayCommand1 command { get; set; }
public Page2()
{
InitializeComponent();
models = new ObservableCollection<model3>()
{
new model3(){username="cherry",Email="cherry#outlook.com"},
new model3(){username="barry",Email="barry#outlook.com"}
};
command = new RelayCommand1(obj => method1((string)obj));
this.BindingContext = this;
}
private void method1(string str)
{
Console.WriteLine("the email is {0}",str);
}
}
public class model3
{
public string username { get; set; }
public string Email { get; set; }
}
Here is the Command that inherit ICommand:
public class RelayCommand1 : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public RelayCommand1(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand1(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_execute(parameter);
}
}
When I tap label, it works fine.
You can set DataTemplate as resource, that would work.

How to Bind Nested List Object Data in Listview Xamarin forms

i have a nested List Object and i want to bind them to the list all my data is proper also i have implemented INotifyChanged Event but the data on the UI Is not displays
here is my Xaml UI
<ListView x:Name ="lstView" Margin="0,5,0,5" VerticalScrollBarVisibility="Always" HasUnevenRows="True" VerticalOptions="FillAndExpand" ItemsSource="{Binding Grouped}" IsGroupingEnabled="true" SelectionMode="None" SeparatorVisibility="None" GroupDisplayBinding="{Binding LongName}" GroupShortNameBinding="{Binding ShortName}">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<Grid Margin="5,20,0,0" RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="95*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="radiochecked.png" VerticalOptions="End" />
<Frame Grid.Column="1" HasShadow="False" HorizontalOptions="Start" Padding="6,2,6,2" BackgroundColor="#608EF6">
<Label Text="{Binding LongName}" TextColor="White" VerticalTextAlignment="Center" ></Label>
</Frame>
</Grid>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="5,0,10,0" HorizontalOptions="FillAndExpand" RowSpacing="0" VerticalOptions="FillAndExpand" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="95*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<BoxView
Grid.Column="0" Grid.Row="0"
BackgroundColor="#566781"
HorizontalOptions="Center"
VerticalOptions="Fill"
WidthRequest="2" />
<Image Grid.Column="0" Grid.Row="1" Source="radiochecked.png" />
<BoxView
Grid.Column="0" Grid.Row="2"
BackgroundColor="#566781"
HorizontalOptions="Center"
VerticalOptions="Fill"
WidthRequest="2" />
<Frame Grid.Column="1" Grid.Row="0" HasShadow="False" Grid.RowSpan="3" Padding="0,0,2,0" Margin="0,10,0,5" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal" VerticalOptions="FillAndExpand">
<BoxView BackgroundColor="{Binding EncounterFrameColor}" WidthRequest="3"></BoxView>
<Grid Margin="0,8,0,0" HorizontalOptions="FillAndExpand" VerticalOptions="Start">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackLayout Spacing="0" Grid.Column="0">
<Label Text="{Binding EncounterMonth}" Margin="3,1,0,0" FontSize="10" TextColor="Black" VerticalOptions="Start" HorizontalOptions="Start"></Label>
<Label Text="{Binding MDate}" Margin="3,2,0,0" FontSize="15" TextColor="Black" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalOptions="Start" HorizontalOptions="Start"></Label>
</StackLayout>
<StackLayout Grid.Column="2" VerticalOptions="Start" Grid.Row="0" HorizontalOptions="FillAndExpand">
<Grid RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image Source="{Binding EncounterImage}" Margin="0,2,0,0" VerticalOptions="Start" Grid.Row="0" Grid.Column="0"/>
<Label Text="{Binding Encounter}" TextColor="Black" FontSize="12" Grid.Row="0" VerticalOptions="Start" Grid.Column="1" ></Label>
<StackLayout Margin="0,0,0,5" Spacing="0" BindableLayout.ItemsSource="{Binding UserVitals}" Grid.Row="1" Grid.Column="1" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Description}" Grid.Column="0" FontSize="10" TextColor="Black" />
<Label Text="{Binding Values}" HorizontalOptions="Start" Grid.Column="2" FontSize="10" TextColor="Black"/>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Grid>
</StackLayout>
</Grid>
</StackLayout>
</Frame>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
i am trying to create Grouping Listview Which is grouping with the Year
here is my Model
public class EncounterFrameModel
{
public string EncounterMonth { get; set; }
public string MDate { get; set; }
public string Comment { get; set; }
// public bool IsReallyAVeggie { get; set; }
public string EncounterFrameColor { get; set; }
public string Image { get; set; }
public string Encounter { get; set; }
// public List<TotalItem> Totals { get;set; }
public string EncounterImage { get; set; }
public ObservableCollection<UserHealthDetails> UserVitals { get; set; }
public EncounterFrameModel()
{
}
}
public class UserHealthDetails
{
public string Description { get; set; }
public string Values { get; set; }
}
public class EncounteredYear
{
public EncounteredYear()
{
encounterFrameModels = new ObservableCollection<EncounterFrameModel>();
}
public string LongName { get; set; }
public string ShortName { get; set; }
public ObservableCollection<EncounterFrameModel> encounterFrameModels { get; set; }
}
can any one help me in binding this data
you could try this:
change your EncounteredYear model like this:
class EncounteredYear:ObservableCollection<EncounterFrameModel>
{
public string LongName { get; set; }
public string ShortName { get; set; }
}
in your page.xaml.cs set your data(Generate data according to your own situation):
ObservableCollection<EncounteredYear> grouped = new ObservableCollection<EncounteredYear>();
var gounp1 = new EncounteredYear() {...};
var gounp2 = new EncounteredYear() {...};
var gounp3 = new EncounteredYear() {...};
gounp1.Add(new EncounterFrameModel() {...});
gounp1.Add(new EncounterFrameModel() {...});
gounp1.Add(new EncounterFrameModel() {...});
gounp1.Add(new EncounterFrameModel() {...});
gounp2.Add(new EncounterFrameModel() {...});
gounp2.Add(new EncounterFrameModel() {...});
gounp2.Add(new EncounterFrameModel() {...});
gounp2.Add(new EncounterFrameModel() {...});
gounp3.Add(new EncounterFrameModel() {...});
gounp3.Add(new EncounterFrameModel() {...});
gounp3.Add(new EncounterFrameModel() {...});
gounp3.Add(new EncounterFrameModel() {...});
grouped.Add(gounp1);
grouped.Add(gounp2);
grouped.Add(gounp3);
lstView.ItemsSource = grouped;// bind the list of the grouplist
then you page's xaml as your before but delete ItemsSource="{Binding Grouped}" and must add <ViewCell> inside <DataTemplate>:
<ListView x:Name ="lstView" Margin="0,5,0,5" VerticalScrollBarVisibility="Always" HasUnevenRows="True" VerticalOptions="FillAndExpand" IsGroupingEnabled="true" SelectionMode="None" SeparatorVisibility="None" GroupDisplayBinding="{Binding LongName}" GroupShortNameBinding="{Binding ShortName}">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Ui is not updating on realtime

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

Hide row if data is empty in ListView

How can I remove the row Comment is on if its null or empty string?
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding EntryDate}" Grid.Column="0" Grid.Row="0"></Label>
<Label Text="{Binding Sleep}" Grid.Column="1" Grid.Row="0"></Label>
<Label Text="{Binding Comment}" Grid.Column="0" Grid.ColumnSpan="4"
Grid.Row="1"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
This is the appropriate case to use a ValueConverter.
All you need to do is create a converter like this:
namespace App.Converters
{
public class TextToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value != null)
if (!(value is string)) return true;
return string.IsNullOrWhiteSpace(value as string) ? false : true;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
And use it on the IsVisible property of Label:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:App.Converters"
x:Class="App.Views.SamplePage">
<ContentPage.Resources>
<ResourceDictionary>
<converters:TextToBoolConverter x:Key="TextToBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding EntryDate}" Grid.Column="0" Grid.Row="0"></Label>
<Label Text="{Binding Sleep}" Grid.Column="1" Grid.Row="0"></Label>
<Label Text="{Binding Comment}" Grid.Column="0" Grid.ColumnSpan="4"
Grid.Row="1"
IsVisible={Binding Comment, Converter={StaticResource TextToBoolConverter}}/>
</Grid>
</ContentPage>
Thus you can reuse it wherever you need.
Your model:
public class MyModel
{
//...other properties ...
public string Comment { get; set; }
public bool HasComment => !string.IsNullOrEmpty(Comment);
}
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding EntryDate}" Grid.Column="0" Grid.Row="0"></Label>
<Label Text="{Binding Sleep}" Grid.Column="1" Grid.Row="0"></Label>
<Label Text="{Binding Comment}" Grid.Column="0" Grid.ColumnSpan="4"
Grid.Row="1" IsVisible = {Binding HasComment}></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>

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;