Xamarin Collectionview Binding Not working - c#

I have a problem where I am using a collectionview and I am trying to get the bindings to work.
I have tried to set the Height, as I saw in other posts, by setting the miniumheight and heightrequest of every element involved, with no success. I have a listview with a textcell and that is the only way I can get this to work.
Model
[Table("Category")]
public class Category
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
}
ViewModel
public class CategoriesViewModel : BaseViewModel
{
public ObservableCollection<Category> Categories { get; }
public Command LoadCategoriesCommand { get; }
public Command AddCategoryCommand { get; }
public CategoriesViewModel()
{
Title = "Categories";
Categories = new ObservableCollection<Category>();
LoadCategoriesCommand = new Command(async () => await ExecuteLoadCategoriesCommand());
AddCategoryCommand = new Command(OnAddCategory);
}
async Task ExecuteLoadCategoriesCommand()
{
IsBusy = true;
try
{
Categories.Clear();
var categories = await DataStore.GetCategoriesAsync();
foreach (var cat in categories)
{
Categories.Add(cat);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
Debug.WriteLine(ex.Message);
}
finally
{
IsBusy = false;
}
}
public void OnAppearing()
{
IsBusy = true;
}
View
xmlns:local="clr-namespace:FreeScanner.ViewModels"
xmlns:model="clr-namespace:FreeScanner.Models"
x:Name="BrowseCategoriesPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Command="{Binding AddCategoryCommand}" />
</ContentPage.ToolbarItems>
<RefreshView x:DataType="local:CategoriesViewModel" Command="{Binding LoadCategoriesCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<CollectionView x:Name="CategoriesListView"
ItemsSource="{Binding Categories}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10" x:DataType="model:Category">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="1"
Grid.Row="1"
Text="{Binding Name}"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<!--<ListView ItemsSource="{Binding Categories}"
x:Name="CategoriesListView"
SelectionMode="None"
RowHeight="50">
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:Category">
<TextCell Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>-->
</RefreshView>
When I debug and hover over the CollectView ItemSource Categories I do see the Count = 1 and I can verify that is correctly loading from the database.

=>Try this it's working well
public class CategoriesViewModel : BaseViewModel
{
public ObservableCollection<Category> Categories { get; set; } = new ObservableCollection<Category>();
public Command LoadCategoriesCommand { get; }
public Command AddCategoryCommand { get; }
public CategoriesViewModel()
{
Title = "Categories";
LoadCategoriesCommand = new Command(async () => await ExecuteLoadCategoriesCommand());
AddCategoryCommand = new Command(OnAddCategory);
}
async Task ExecuteLoadCategoriesCommand()
{
IsBusy = true;
try
{
Categories.Clear();
var categories = await DataStore.GetCategoriesAsync();
foreach (var cat in categories)
{
Categories.Add(new Category{Name=cat.Name});
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
Debug.WriteLine(ex.Message);
}
finally
{
IsBusy = false;
}
}
public void OnAppearing()
{
IsBusy = true;
}
=>This is my Xaml
<CollectionView x:Name="CourseList" IsVisible="{Binding IsVisibleCourse}" ItemsSource="{Binding Courses}" >
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="2"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="5" Spacing="-6">
<Frame BorderColor="LightGray" HeightRequest="{OnIdiom Phone=140,Tablet=210}" CornerRadius="10" HasShadow="False" Padding="5">
<StackLayout Padding="5" Orientation="Vertical" Spacing="5">
<ffimageloading:CachedImage x:Name="Pic" LoadingDelay="0"
Margin="0,5,0,0" WidthRequest="{OnIdiom Phone=60,Tablet=100}"
HeightRequest="{OnIdiom Phone=60,Tablet=100}" Source="{Binding ImageURL}"
HorizontalOptions="CenterAndExpand" VerticalOptions="Center"
BackgroundColor="Transparent" Aspect="Fill" >
<ffimageloading:CachedImage.Transformations>
<ffTransformations:CircleTransformation />
</ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>
<Label Text="{Binding Name}" MaxLines="2" Style="{StaticResource TextDefaultStyle}" TextColor="Black" HorizontalTextAlignment="Center" VerticalOptions="Fill"/>
<Label Text="{Binding Description}" MaxLines="2" Style="{StaticResource TextMicroStyle}" HorizontalTextAlignment="Center" VerticalOptions="Fill" FontAttributes="Bold"/>
</StackLayout>
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1"
Command="{Binding Path=BindingContext.CourseListCommand, Source={x:Reference CourseList}}" CommandParameter="{Binding .}"/>
</Frame.GestureRecognizers>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

Related

How to select all items in Listview at once or get every primary key from every row?

So far I've got this which gets the index number of the selected item in the Listview and then i use that to get data from my database. Now i need a away to get all the row index numbers to get the id and symbol and run it during a listview swipe down.
async void myPriceList_ItemSelected(System.Object sender, Xamarin.Forms.SelectedItemChangedEventArgs e)
{
userInput selectedOne = (userInput)e.SelectedItem;
var id = selectedOne.Id.ToString();
var symbol = selectedOne.Pair.ToString();
using (SQLiteConnection conn = new SQLiteConnection(App.FilePath))
{
conn.CreateTable<userInput>();
var userInfo = conn.Table<userInput>().ToList();
myPriceList.ItemsSource = userInfo;
var buyAmount = conn.Get<userInput>(id).buyAmount;
var buyPair = conn.Get<userInput>(id).Pair.ToString();
HttpClient client = new HttpClient();
var response = await client.GetStringAsync("https://api.binance.com/api/v3/ticker/price?symbol=" + symbol);
var cryptoconverted = JsonConvert.DeserializeObject<Crypto>(response);
var currentPriceDouble = double.Parse(cryptoconverted.price);
var finalAnswer = double.Parse(cryptoconverted.price) * double.Parse(buyAmount);
conn.Execute("UPDATE userInput SET worth = " + finalAnswer + " where Id= " + id);
};
This is my list view
<Grid Margin="-10,0,0,0" Padding="7,0,7,0">
<ListView x:Name="myPriceList" IsPullToRefreshEnabled="True" RefreshCommand="{Binding RefreshCommand}" IsRefreshing="{Binding IsRefreshing}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="33*" />
<ColumnDefinition Width="33*" />
<ColumnDefinition Width="30*" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Vertical" Grid.Column="0" Margin="10,0,0,0">
<Label Text="{Binding Pair}" FontAttributes="Bold" TextColor="Black" FontSize="12" Margin="0,0,0,-5"/>
<Label Text="{Binding buyPrice}" TextColor="DarkSlateGray" FontSize="10" HorizontalTextAlignment="Start" Margin="0,0,0,-5"/>
<Label Text="{Binding Id}" TextColor="DarkSlateGray" FontSize="10" HorizontalTextAlignment="Start"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Column="1" >
<Button Text="Delete" Clicked="Button_Clicked" CommandParameter="{Binding ItemName}"></Button>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Column="2">
<Label Text="{Binding worth}" FontAttributes="Bold" TextColor="Black" FontSize="12" Margin="0,0,0,-5" HorizontalTextAlignment="End"/>
<Label Text="{Binding buyAmount}" TextColor="DarkSlateGray" FontSize="10" HorizontalTextAlignment="End" Margin="0,0,0,-5"/>
<Label Text="{Binding spent}" TextColor="DarkSlateGray" FontSize="10" HorizontalTextAlignment="End"/>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
this is the refresh
protected override void OnAppearing()
{
base.OnAppearing();
myPriceList.RefreshCommand = new Command(() =>
{
//It should be here
myPriceList.IsRefreshing = false;
});
}
I want to whatever is in my Listview.selecteditem to be used under refresh command
If you want to use ListView.SelectedItem in ListView's RefreshCommand, you can use ListView's SelectedItem binding.
I do one sample to get ListView's SelectedItem in ListView's RefreshCommand.
<ListView
x:Name="listPlatforms"
IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsRefreshing}"
ItemsSource="{Binding mylist}"
RefreshCommand="{Binding RefreshCommand}"
SelectedItem="{Binding selecteditem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Id}" />
<Label Text="{Binding Name}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public partial class Page14 : ContentPage
{
public Page14()
{
InitializeComponent();
this.BindingContext = new userviewmodel();
}
}
public class userviewmodel:ViewModelBase
{
public ObservableCollection<userInput> mylist { get; set; }
public ICommand RefreshCommand { get; }
private userInput _selecteditem;
public userInput selecteditem
{
get { return _selecteditem; }
set
{
_selecteditem = value;
RaisePropertyChanged("selecteditem");
}
}
private bool _isRefreshing = false;
public bool IsRefreshing
{
get { return _isRefreshing; }
set
{
_isRefreshing = value;
RaisePropertyChanged("IsRefreshing");
}
}
public userviewmodel()
{
mylist = new ObservableCollection<userInput>();
for(int i=0; i<30; i++)
{
userInput user = new userInput();
user.Id = i.ToString();
user.Name = "cherry " + i;
mylist.Add(user);
}
RefreshCommand = new Command(async () =>
{
IsRefreshing = true;
if(selecteditem!=null)
{
Console.WriteLine(selecteditem.Name);
}
//RefreshData();
IsRefreshing = false;
});
}
}
ViewModelBase is class that implementing INotifyPropertyChanged, to notify data update.
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Exception on Xamarin: System.ObjectDisposedException: Cannot access a disposed object 'Xamarin.Forms.Platform.Android.FastRenderers.LabelRenderer'

I am using Xamarin.Forms to build an app for Android and I'm currently getting the following error: System.ObjectDisposedException: Cannot access a disposed object 'Xamarin.Forms.Platform.Android.FastRenderers.LabelRenderer'. The Xamarin.Forms version I am using is 4.8.0.1364
My code for the XAML is the following:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView
x:Class="Peripass.YardAssetManagementApp.UI.Views.MainTaskListViewContent"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:Peripass.Mobile.Framework.Converters;assembly=Peripass.Mobile.Framework"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:uiControls="clr-namespace:Peripass.Mobile.Framework.UIControls;assembly=Peripass.Mobile.Framework"
mc:Ignorable="d"
x:Name="tasksPage">
<ContentView.Resources>
<ResourceDictionary>
<converters:ItemTappedEventArgsToTappedItemConverter x:Key="ItemTappedConverter" />
</ResourceDictionary>
</ContentView.Resources>
<ContentView.Content>
<!-- All Tasks -->
<StackLayout
BackgroundColor="White"
VerticalOptions="FillAndExpand">
<!-- ActivityIndicator -->
<StackLayout
Padding="0,20,0,0"
BackgroundColor="White"
IsVisible="{Binding Model.ShowLoadingIndicator}">
<ActivityIndicator BackgroundColor="White"
Color="#28aa90"
HeightRequest="40"
WidthRequest="40"
IsRunning="{Binding Model.ShowLoadingIndicator}"
IsVisible="{Binding Model.ShowLoadingIndicator}">
</ActivityIndicator>
<Label FontSize="14" Text="fetching tasks" TextColor="DimGray" HorizontalTextAlignment="Center" HorizontalOptions="FillAndExpand"></Label>
</StackLayout>
<RefreshView Command="{Binding RefreshCommand}" IsRefreshing="{Binding IsRefreshing, Mode=OneWay}">
<CollectionView x:Name="tasks" ItemsSource="{Binding Model.AllTasks}" ItemSizingStrategy="MeasureAllItems" VerticalOptions="FillAndExpand">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout BackgroundColor="{Binding RowBackGroundColor}">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer CommandParameter="{Binding TaskId}" Command="{Binding Source={x:Reference tasks}, Path=BindingContext.TappedGotoTaskDetailCommand}"/>
</StackLayout.GestureRecognizers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="73" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<uiControls:PpIcon
Grid.Row="0"
Grid.Column="0"
Margin="5"
IconChar="{Binding LeftIconChar}"
IconColor="{Binding LeftIconColor}"
IconSize="42" />
<Grid Grid.Row="0" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="50*" />
<RowDefinition Height="50*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label
FontAttributes="Bold"
FontSize="21"
HorizontalTextAlignment="Start"
LineBreakMode="TailTruncation"
Text="{Binding TaskLine1}"
TextColor="{StaticResource PeripassBlack}"
TranslationY="7"
VerticalTextAlignment="Center" />
<StackLayout
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
Margin="0"
Padding="0"
Orientation="Horizontal"
Spacing="0"
TranslationX="4">
<Label
FontAttributes="Bold"
FontSize="21"
HorizontalOptions="End"
HorizontalTextAlignment="Start"
Text="{Binding StepProgressLineStepsDone}"
TextColor="{Binding RightIconColor}"
VerticalTextAlignment="Center" />
<Label
FontSize="21"
HorizontalOptions="End"
HorizontalTextAlignment="Start"
Text="/"
TextColor="{Binding RightIconColor}"
VerticalTextAlignment="Center" />
<Label
FontSize="21"
HorizontalOptions="End"
HorizontalTextAlignment="Start"
Text="{Binding StepProgressLineStepsTotal}"
TextColor="{Binding RightIconColor}"
VerticalTextAlignment="Center" />
</StackLayout>
<Label
Grid.Row="1"
Grid.Column="0"
FontSize="16"
HorizontalTextAlignment="Start"
LineBreakMode="TailTruncation"
Text="{Binding TaskLine2}"
TextColor="{StaticResource PeripassBlack}"
VerticalOptions="StartAndExpand"
VerticalTextAlignment="Center" />
</Grid>
<uiControls:PpIcon
Grid.Row="0"
Grid.Column="2"
Margin="15"
IconChar="{Binding RightIconChar}"
IconColor="{Binding RightIconColor}"
IconSize="42" />
<Label
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
FontSize="16"
HorizontalTextAlignment="Start"
LineBreakMode="TailTruncation"
Text="{Binding DisplayName}"
TextColor="{StaticResource PeripassBlack}"
VerticalOptions="StartAndExpand"
VerticalTextAlignment="Center"
IsVisible="{Binding Source={x:Reference tasksPage}, Path=BindingContext.Model.IsSearching}"
/>
</Grid>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.EmptyView>
<StackLayout>
<StackLayout HeightRequest="100" BackgroundColor="#D6D6D6" Margin="10,10,10,10">
<Label HorizontalOptions="Center" VerticalOptions="CenterAndExpand" FontSize="20" Text="No tasks available" TextColor="{StaticResource PeripassBlack}"/>
</StackLayout>
</StackLayout>
</CollectionView.EmptyView>
</CollectionView>
</RefreshView>
</StackLayout>
</ContentView.Content>
</ContentView>
The code for the ViewModel
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Peripass.ApiModels;
using Peripass.Mobile.Framework.DependencyInterfaces;
using Peripass.YardAssetManagementApp.Data;
using Peripass.YardAssetManagementApp.Data.LocalDataServices;
using Peripass.YardAssetManagementApp.Data.Syncing.QueueItemSyncActions;
using Peripass.YardAssetManagementApp.DomainModel.V1;
using Peripass.YardAssetManagementApp.DomainModel.V1.Extensions;
using Peripass.YardAssetManagementApp.Events;
using Peripass.YardAssetManagementApp.Icons;
using Peripass.YardAssetManagementApp.Models;
using Peripass.YardAssetManagementApp.MVVM;
using Peripass.YardAssetManagementApp.UI.TopHeaders;
using Xamarin.Forms;
namespace Peripass.YardAssetManagementApp.ViewModels {
public class MainTaskListViewModel : ViewModelBase<MainTaskListModel> {
private readonly ILocalTaskDataService _localTaskDataService;
private readonly ILocalLocationDataService _localLocationDataService;
private readonly IToMobileTasksSyncer _toMobileTasksSyncer;
private List<YardOperatorTask> _tasks;
private readonly ILocalUserDataService _localUserDataService;
public MainTaskListViewModel(ILocalTaskDataService localTaskDataService, ILocalLocationDataService localLocationDataService, IToMobileTasksSyncer toMobileTasksSyncer, ILocalUserDataService localUserDataService) {
_localTaskDataService = localTaskDataService;
_localLocationDataService = localLocationDataService;
_toMobileTasksSyncer = toMobileTasksSyncer;
_localUserDataService = localUserDataService;
MessagingCenter.Unsubscribe<ToMobileTasksSyncer>(this, EventTypes.FetchingTasks.ToString());
MessagingCenter.Unsubscribe<ToMobileTasksSyncer>(this, EventTypes.LocalTasksUpdated.ToString());
MessagingCenter.Unsubscribe<IQueueItemSyncAction>(this, EventTypes.LocalTasksUpdated.ToString());
MessagingCenter.Unsubscribe<ToMobileTasksSyncer>(this, EventTypes.FetchingTasksFailed.ToString());
SubscribeToTaskFetches();
_tasks = new List<YardOperatorTask>();
}
public ICommand TappedGotoTaskDetailCommand => new Command<int>(async (taskId) => await ExecuteGotoTaskDetail(taskId));
public ICommand RefreshCommand => new Command(ExecuteRefreshCommand);
private void SubscribeToTaskFetches() {
MessagingCenter.Subscribe<ToMobileTasksSyncer>(this, EventTypes.FetchingTasks.ToString(), sender => {
Model.ShowLoadingIndicator = true;
});
MessagingCenter.Subscribe<ToMobileTasksSyncer>(this, EventTypes.LocalTasksUpdated.ToString(), _ => OnTasksUpdated());
MessagingCenter.Subscribe<IQueueItemSyncAction>(this, EventTypes.LocalTasksUpdated.ToString(), _ => OnTasksUpdated());
MessagingCenter.Subscribe<ToMobileTasksSyncer>(this, EventTypes.FetchingTasksFailed.ToString(), sender => {
Model.ShowLoadingIndicator = false;
});
}
private void OnTasksUpdated() {
Model.ShowLoadingIndicator = false;
GetTasks();
MapToModel();
}
public bool IsRefreshing { get; set; }
private async void ExecuteRefreshCommand() {
try {
if (IsRefreshing) {
return;
}
IsRefreshing = true;
await _toMobileTasksSyncer.SyncAllData();
}
catch {
await NavigationService.NavigateToViewModelAsync<GenericExceptionPageViewModel>();
}
finally {
IsRefreshing = false;
}
}
public override void OnInit(object param) {
SetTopHeader();
}
private void SetTopHeader() {
var topHeader = new TopHeaderForAllTasksContentView(SearchTextChangedAction, StopSearchAction);
topHeader.SetLine("Task List");
NavigationService.SetTopHeader(TopHeaderTappedBackCommand, topHeader);
NavigationService.SetTopHeaderVisible(true);
}
public override void OnAppeared() {
GetTasks();
MapToModel();
}
private void GetTasks() {
_tasks = _localTaskDataService
.GetAllTasks()
.Where(task => task.Status == TaskStatusEnum.Unassigned || task.Status == TaskStatusEnum.Started && task.AssignedOperatorId == _localUserDataService.GetCurrentUser().UserTechnicalId)
.ToList();
}
private async Task ExecuteGotoTaskDetail(int taskId) {
await NavigationService.NavigateToViewModelAsync<TaskDetailViewModel>(taskId);
}
private void StopSearchAction() {
DependencyService.Get<IDeviceKeyboardHelper>().HideKeyboard();
MapToModel();
}
private void SearchTextChangedAction(string searchText) {
MapToModel(searchText);
}
private void TopHeaderTappedBackCommand() {
NavigationService.ShowMenu();
}
private void MapToModel(string searchOn = "") {
Model.IsSearching = searchOn != "";
Model.AllTasks = new ObservableCollection<TaskItem>();
Model.ShowMessageNoTasksAvailable = !Model.ShowLoadingIndicator && _tasks.All(task => task.Status == TaskStatusEnum.Finished);
AddUncompletedTasks(searchOn);
}
private void AddUncompletedTasks(string searchOn = "") {
if (_tasks == null) return;
var tasks = _tasks.Where(c => c.Status != TaskStatusEnum.Finished).ToArray();
if (searchOn != "") {
tasks = _tasks.Where(task => task.GetSearchableTaskString(_localLocationDataService.GetLocations()).Contains(searchOn.ToUpper(CultureInfo.InvariantCulture))).ToArray();
}
for (var i = 0; i < tasks.Length; i++) {
AddUncompletedTask(i, tasks[i]);
}
}
private void AddUncompletedTask(int index, YardOperatorTask task) {
var rowBackgroundColor = Color.FromHex("FFFFFF");
if (index % 2 == 0) {
rowBackgroundColor = Color.FromHex("F6F6F6");
}
var leftIconChar = CalcLeftIconChar(task);
var iconColor = CalcIconColor(task);
var rightIconChar = CalcRightIconChar(task);
var stepProgressLineStepsDone = task.TaskSteps.Count(c => c.IsDone).ToString();
var stepProgressLineStepsTotal = task.TaskSteps.Count().ToString();
Model.AllTasks.Add(new TaskItem {
TaskIsFinished = false,
TaskId = task.Id,
LeftIconChar = leftIconChar,
LeftIconColor = iconColor,
TaskLine1 = task.GetTaskDisplayName(_localLocationDataService.GetLocations()),
TaskLine2 = task.Template.Name,
RightIconChar = rightIconChar,
RightIconColor = iconColor,
RowBackGroundColor = rowBackgroundColor,
StepProgressLineStepsDone = stepProgressLineStepsDone,
StepProgressLineStepsTotal = stepProgressLineStepsTotal,
DisplayName = task.Asset?.Name ?? task.Visitor.Name
});
}
private static char CalcRightIconChar(YardOperatorTask task) {
switch (task.Status) {
case TaskStatusEnum.Unassigned:
return IconChar.For(IconsEnum.TaskListTaskIsUnassiged);
case TaskStatusEnum.Assigned:
case TaskStatusEnum.Started:
return IconChar.For(IconsEnum.TaskListTaskStarted);
default:
return ' ';
}
}
private static Color CalcIconColor(YardOperatorTask task) {
switch (task.Status) {
case TaskStatusEnum.Unassigned:
return IconColor.For(IconsEnum.TaskListTaskIsUnassiged);
case TaskStatusEnum.Assigned:
case TaskStatusEnum.Started:
return IconColor.For(IconsEnum.TaskListTaskStarted);
default:
return Color.Black;
}
}
private static char CalcLeftIconChar(YardOperatorTask task) {
if (task.TaskSteps.Any(c => c.FieldDefinitionType == FieldDefinitionType.MoveToLocation)) {
return IconChar.For(IconsEnum.TaskListTaskIsMove);
}
else {
return IconChar.For(IconsEnum.TaskListTaskIsInspection);
}
}
}
}
I believe that this piece of code in the XAML is the culprit. More specific, the IsVisible property of the label. If I remove that, the exception does not seem to happen.
<Label
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
FontSize="16"
HorizontalTextAlignment="Start"
LineBreakMode="TailTruncation"
Text="{Binding DisplayName}"
TextColor="{StaticResource PeripassBlack}"
VerticalOptions="StartAndExpand"
VerticalTextAlignment="Center"
IsVisible="{Binding Source={x:Reference tasksPage}, Path=BindingContext.Model.IsSearching}"
/>
I have searched for some time now and tried different things but nothing seems to work. If you need more information, please do ask.
This issue has been fix in the latest version of Xamarin.forms 4.8.0.1687.
Any one who meet this issue please update your Xamarin.forms version.
Here are some relevant threads in the Github.
Cannot access a disposed object
Cannot access a disposed object FastRenderers.LabelRenderer

Xamarin Forms Command Binding inside ListView is not working

i'm trying to bind a command to a button inside a listView, but without success. I follow all other answers posted here, like this one:
Xamarin Forms Button Command binding inside a ListView
The actual result is that nothing happens. A thing that i notice is that visual studio, when i type after x:Reference suggests me just GridWebcam, like if it doesn't see other reference elements. What can i do?
Here my code:
<ContentPage
...
x:Name="WebcamList">
<ContentPage.Resources>
...
<ContentPage.Content>
<ListView ItemsSource="{Binding ListOfWebcam}"
SeparatorVisibility="None"
CachingStrategy="RecycleElement"
RowHeight="250"
VerticalOptions="FillAndExpand"
x:Name="ListWebcam">
<ListView.Header>
<StackLayout x:Name="HeaderStackLayout"
Padding="5,25,0,30"
Orientation="Horizontal"
HorizontalOptions="FillAndExpand">
<Label x:Name="LabelHeader"
Text="Webcam:"
FontSize="Large"
FontAttributes="Bold"
TextColor="{x:Static statics:Palette.PrimaryColor}"
VerticalOptions="Center"
HorizontalOptions="Start" Margin="10,0,0,0"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<controls:ExtendedViewCell IsEnabled="False">
<controls:ExtendedViewCell.View>
<Grid x:Name="GridWebcam">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Frame Grid.Column="1"
Grid.RowSpan="2"
CornerRadius="20"
BackgroundColor="{x:Static statics:Palette.PrimaryColor}"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
HasShadow="True"
Margin="5,10">
<StackLayout>
<Label Text="{Binding t_str_vid,Converter={StaticResource WebcamNameConverter}}"
FontSize="Medium"
TextColor="White"
FontAttributes="Bold"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
</Label>
<Label TextColor="White"
FontSize="Medium"
Text="{Binding direzione,Converter={StaticResource DirectionToStringConverter}}"/>
<StackLayout Orientation="Horizontal">
<ffimageloading:CachedImage LoadingPlaceholder="Rolling.gif"
DownsampleToViewSize="False"
VerticalOptions="FillAndExpand"
HorizontalOptions="StartAndExpand"
Source="{Binding image1}"/>
<iconize:IconButton Text="fas-play-circle"
FontSize="50"
HorizontalOptions="EndAndExpand"
VerticalOptions="EndAndExpand"
TextColor="White"
Command="{Binding BindingContext.OpenVideoWebcamCommand, Source={x:Reference WebcamList}}"
CommandParameter="{Binding .}"
BackgroundColor="Transparent"/>
</StackLayout>
</StackLayout>
</Frame>
</Grid>
</controls:ExtendedViewCell.View>
</controls:ExtendedViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
```
public class WebcamListViewModel : BaseViewModel
{
public ICommand OpenVideoWebcamCommand { set; get; }
private List<Webcam> _ListOfWebcam { get; set; }
public List<Webcam> ListOfWebcam
{
get { return _ListOfWebcam; }
set
{
_ListOfWebcam = value;
OnPropertyChanged();
}
}
private Task DownloadFramesTask;
CancellationTokenSource tokenSourceDownloadFrames = new CancellationTokenSource();
CancellationToken cancellationTokenDownloadFrames;
public WebcamListViewModel(INavigationService navigationService, IApiAutostradeManagerFactory apiAutostradeManagerFactory) : base(navigationService,apiAutostradeManagerFactory)
{
OpenVideoWebcamCommand = new Command<Webcam>(async (webcam) => {
await navigationService.NavigateAsync(Locator.WebcamVideoPopUpPage);
Messenger.Default.Send(new InfoWebcamVideoMessage(webcam.c_mpr, webcam.c_uuid, webcam.t_str_vid));
});
}
Well it could be related to this mysterious controls:ExtendedViewCell of yours :)
Also did you disable the ListView selection: <ListView ... SelectionMode="None" /> ?
As Roubachof said that I don't know if it is related to controls:ExtendedViewCell,please check if you have binding BindingContext, then you can take a look the following code:
<StackLayout>
<ListView x:Name="listview1" ItemsSource="{Binding persons}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Id}" />
<Label Text="{Binding name}" />
<Button
Command="{Binding BindingContext.command, Source={x:Reference listview1}}"
CommandParameter="{Binding Id}"
Text="Delete item" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
public partial class Page1 : ContentPage
{
public ObservableCollection<person> persons { get; set; }
public RelayCommand1 command { get; set; }
public Page1 ()
{
InitializeComponent ();
persons = new ObservableCollection<person>();
for(int i =0;i<20;i++)
{
person p = new person()
{
Id = i,
name = "cherry" + i
};
persons.Add(p);
command = new RelayCommand1(obj => method1((int)obj));
}
this.BindingContext = this;
}
public void method1(int Id)
{
persons.RemoveAt(Id);
//IEnumerable<person> list = persons.Where(x => x.Id == Id);
//foreach (person m in list)
//{
//}
}
}
public class person
{
public int Id { get; set; }
public string name { get; set; }
}

MVVM Navigation Force Close Xamarin Forms

I try using mvvm in my xamarin forms but i'm still litle bit confused with the navigation in each page, I Already Create Interface and NavigationService to handle all Navigation in my Xamarin Forms, there is no error code line but when i click the buton and try to navigate to other page it always crash. Here is some of my code
My Interface
namespace KGVC.Interfaces
{
public interface INavigationService
{
void NavigateToDashboard();
void NavigateToLogout();
void NavigateBack();
void gotoNews();
void goEvent();
void gotoKGCash();
void gotoCardCommnunity();
void gotoSetting();
void gotoNearbyLocation();
}
}
my navigationservice
namespace KGVC.Services
{
public class NavigationService : INavigationService
{
public void goEvent()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new EventPage());
}
public void gotoCardCommnunity()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new CardCommunityPage());
}
public void gotoKGCash()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new KGCashPage());
}
public void gotoNearbyLocation()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new StoreMaps());
}
public void gotoNews()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new RssFeedView());
}
public void gotoSetting()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new SettingPages());
}
public void NavigateBack()
{
throw new NotImplementedException();
}
public void NavigateToDashboard()
{
var currentPage = GetCurrentPage();
Application.Current.MainPage = new MainPage();
}
public void NavigateToLogout()
{
var currentPage = GetCurrentPage();
Application.Current.MainPage = new NewPageLogin();
}
private Page GetCurrentPage()
{
var currentPage = Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
return currentPage;
}
}
}
my view model
public class GridMenuViewModel
{
public ICommand gotoNews { get; private set; }
public ICommand goEvent { get; private set; }
public ICommand gotoKGCash { get; private set; }
public ICommand gotoSetting { get; private set; }
public ICommand gotoNearbyLocation { get; private set; }
public GridMenuViewModel()
{
gotoNews = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoNews();
});
goEvent = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.goEvent();
});
gotoKGCash = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoKGCash();
});
gotoSetting = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoSetting();
});
gotoNearbyLocation = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoNearbyLocation();
});
}
}
And my view
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
NavigationPage.HasNavigationBar="True"
NavigationPage.BackButtonTitle="False"
BindingContext="{Binding GridMenuViewModel, Source={StaticResource Locator}}"
xmlns:control="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
xmlns:local="clr-namespace:KGVC.Views.MainPages"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KGVC.Views.MainPages.GridMenu"
Title="HOME"
>
<ContentPage.Content>
<StackLayout >
<StackLayout BackgroundColor="##CEB053">
<StackLayout HeightRequest="35" BackgroundColor="##CEB053" Orientation="Horizontal">
<Label FontAttributes="Italic" TextColor="Black" Margin="9" Text="Hello," FontSize="15"/>
<Label TextColor="Black" Margin="9" Text="John Doe" FontSize="15" FontAttributes="Bold"/>
</StackLayout>
<StackLayout Padding="0" HeightRequest="30" BackgroundColor="#E3E6E3" Orientation="Horizontal">
<Image Margin="5" Source="ic_logo.png"/>
<Label Text="Points" Margin="5" FontSize="13" TextColor="Black"/>
</StackLayout>
</StackLayout>
<StackLayout HeightRequest="220" VerticalOptions="StartAndExpand">
<control:CarouselView HeightRequest="185" ItemsSource="{Binding MyDataSource}" Position="{Binding Position, Mode=TwoWay}">
<control:CarouselView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Image}"/>
</DataTemplate>
</control:CarouselView.ItemTemplate>
</control:CarouselView>
<local:CarouselIndicators IndicatorHeight="9" IndicatorWidth="9" UnselectedIndicator="unselected_circle.png" SelectedIndicator="selected_circle.png" Position="{Binding Position}" ItemsSource="{Binding MyDataSource}" />
</StackLayout>
<ScrollView IsClippedToBounds="True" VerticalOptions="StartAndExpand" Orientation="Vertical" >
<Grid x:Name="controlGrid" VerticalOptions="StartAndExpand" HeightRequest="370" Margin="15">
<Grid.RowDefinitions>
<RowDefinition Height="0" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110" />
<ColumnDefinition Width="110" />
<ColumnDefinition Width="110" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="0" >
<Button Image="ic_account.png" Margin="5"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="MY ACCOUNT" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="1">
<Button Margin="5" Command="{Binding gotoCardCommunity}" Image="ic_card.png"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="CARD" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="2">
<Button Margin="5" Command="{Binding goEvent}" Image="ic_event"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="PROMO" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Grid.Row="2" Grid.Column="0" Orientation="Vertical">
<Button Margin="5" Command="{Binding gotoNearbyLocation}" Image="ic_store"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="STORE LOCATIONS" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="2" Grid.Column="1">
<Button Margin="5" Command="{Binding gotoNews}" Image="ic_news"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="NEWS" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Grid.Row="2" Grid.Column="2" Orientation="Vertical">
<Button Margin="5" Command="{Binding gotoKGCash}" Image="ic_kgcash"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="E-WALLET" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="3" Grid.Column="0">
<Button Margin="5" Image="ic_ecommerce"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="E-COMMERCE" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="3" Grid.Column="1">
<Button Margin="5" Command="{Binding gotoSetting}" Image="ic_pointsummary.png"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="POINT SUMMARY" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="3" Grid.Column="2">
<Button Margin="5" Command="{Binding gotoSetting}" Image="ic_setting"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="SETTINGS" HorizontalOptions="Center"/>
</StackLayout>
</Grid>
</ScrollView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
i already try change the navigation service to use pushmodalasync, make the navigation async but still crash, Anyone can help me ? and i'm not using prism , mvvmlight and other 3rd party mvvm nuget
It depends on your MainPage. Did you check if GetCurrentPage() actually returns something?
Try to change the GetCurrentPage() to:
Page GetCurrentPage() =>
Application.Current.MainPage.Navigation?.NavigationStack?.LastOrDefault() ??
Application.Current.MainPage;
Another problems that I spotted:
1. C# naming conventions are different from Java. Method names should start with a capital letter. Currently you have a pure mix.
2. Initialising the BindingContext in XAML the way you did will create the ViewModel twice due to a bug. Change it to:
<ContentPage
xmlns:vm="your-namespace.vm"
...>
<ContentPage.BindingContext>
<vm:GridMenuViewModel />
</ContentPage.BindingContext>
</ContentPage>
3. No need to recreate the NavigationService for each command. Reuse it in your ViewModel.
4. You have some corrupted XAML:
<StackLayout BackgroundColor="##CEB053">
Fix the hex code. Generally speaking you could enable XAMLC so you would get notified about XAML errors while building your code.
5. In order to use PushAsync your MainPage should be wrapped by NavigationPage.
6. You need to await async code execution:
public async Task GoToCardCommnunity()
{
var currentPage = GetCurrentPage();
await currentPage.Navigation.PushAsync(new CardCommunityPage());
}
Check over the list above and pay attention to the application output and exceptions.

Xamarin Forms ListView grouping bind issue

I have been trying to play around Xamarin Forms for a while and then came across to the Listview Grouping. I am not getting done its showing blank list. Please give me help to find where I am going wrong? Thanks in advance
However, My class domain looks like:
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; }
}
My View Model property look like
public IEnumerable<KeyValuePair<string, ObservableCollection<LineItemTaxDto>>> ReceiptTaxList { get; set; }
My expecting result look like:
My xaml code below
<ListView x:Name="TaxListView"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
ItemsSource="{Binding Invoice.ReceiptTaxList}"
IsGroupingEnabled="true">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Key}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<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 Text="{Binding TaxName}" Grid.Row="0" Grid.Column="0" 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>
EDIT
I am set value in view will appear method
Invoice.ReceiptTaxList = Invoice.InvoiceLineItems.Select(x => { return new KeyValuePair<string, ObservableCollection<LineItemTaxDto>>(x.TaxName, x.LineItemTaxes); });
The value was set properly
I have solved this tricky code not using grouping but now its work as expected
My ViewModel Code
var TaxList = Invoice.InvoiceLineItems.Where(x => x.TaxId > 1).GroupBy(y=>y.TaxId > 1).Select(x =>
{
return new KeyValuePair<LineItemTaxDto, ObservableCollection<LineItemTaxDto>>(new LineItemTaxDto()
{
InvoiceLineItemId = x.First().Id,
InvoiceId = x.First().InvoiceId,
TaxId = x.First().TaxId,
TaxRate = x.First().TaxRate,
TaxAmount = x.Sum(a=>a.TaxAmount),
TaxName = taxlabel + " (" + x.First().TaxName + ")"
}, x.First().LineItemTaxes);
});
var taxes = new ObservableCollection<LineItemTaxDto>();
foreach (var tax in TaxList.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;
My Xaml Code
<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>
You must use a list of list as items source on listview to get it working. I recommend you to create a class with the properties you want to show at header like this:
public class TaxesObservableCollection<T> : ObservableCollection<T> // Think about to implement INotifyPropertyChanged too, I guess it will be usefull
{
public TaxesObservableCollection(IEnumerable<T> collection, string taxGroupName) : base(collection)
{
TaxGroupName = taxGroupName;
}
private bool taxGroupName;
public bool TaxGroupName
{
get { return taxGroupName; }
set { taxGroupName = value; }
}
}
In your view model:
public IEnumerable<TaxesObservableCollection<LineItemTaxDto>> ReceiptTaxList { get; set; }
Your ListView:
(...) // The rest of it as you did
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding TaxGroupName}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
(...) // The rest of it as you did
And you fill it this way:
Invoice.ReceiptTaxList = Invoice.InvoiceLineItems.Select(x => { return new TaxesObservableCollection<LineItemTaxDto>(x.LineItemTaxes, x.TaxName); }).ToList();
It should works, please let me know if is that what you wanted.

Categories

Resources