I’m kind of stuck and not getting anywhere. Here is my problem:
I want to populate a ListView with the data from a MySql database. Here is my class which contains the database queries:
DBConnection:
public ObservableRangeCollection<ExpenseReport> GetDataExpenseReport()
{
if (OpenConnection() == true)
{
DataExpense = new ObservableRangeCollection<ExpenseReport>();
MySqlCommand sc = new MySqlCommand();
sc.CommandText = "SELECT * FROM t_expensereport WHERE c_inputuser = @userid";
sc.Parameters.AddWithValue("@userid", User.Id);
sc.Connection = myConn;
MySqlDataReader dr = sc.ExecuteReader();
while (dr.Read())
{
DataExpense.Add(new ExpenseReport
{
Date = (DateTime)dr["c_date"],
Reason = (string)dr["c_reason"],
TripThereAndBack = (string)dr["c_tripThereAndBack"],
Vehicle = (string)dr["c_vehicle"],
Kilometers = (double)dr["c_kilometers"],
EuroProKm = (double)dr["c_euroProKm"],
TripCost = (double)dr["c_tripCost"],
Maut = (double)dr["c_maut"],
ParkingLot = (double)dr["c_parkingLot"],
Other = (double)dr["c_other"],
Accommodation = (double)dr["c_accommodation"],
Meal = (double)dr["c_meal"],
TrainTicket = (double)dr["c_trainTicket"]
});
}
dr.Close();
return DataExpense;
}
return null;
}
My Model ExpenseReport:
public class ExpenseReport
{
public DateTime Date { get; set; }
public string Reason { get; set; }
public string TripThereAndBack { get; set; }
public string Vehicle { get; set; }
public double Kilometers { get; set; }
public double EuroProKm { get; set; }
public double TripCost { get; set; }
public double Maut { get; set; }
public double ParkingLot { get; set; }
public double Other { get; set; }
public double Accommodation { get; set; }
public double Meal { get; set; }
public double TrainTicket { get; set; }
}
View:
<?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:viewmodels="clr-namespace:Magazin.ViewModels.Dashboard"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:model="clr-namespace:Magazin.Models"
x:Class="Magazin.Views.Dashboard.OverviewExpenseReportView"
Title="Übersicht Spesen">
<ContentPage.BindingContext>
<viewmodels:OverviewExpenseReportViewModel/>
</ContentPage.BindingContext>
<ContentPage.Behaviors>
<xct:EventToCommandBehavior
EventName="Appearing"
Command="{Binding RefreshCommand}" />
</ContentPage.Behaviors>
<ContentPage.Content>
<StackLayout>
<ListView
x:Name="OverviewER"
CachingStrategy="RecycleElement"
BackgroundColor="Transparent"
ItemsSource="{Binding ExpenseReport}"
HasUnevenRows="True"
SeparatorVisibility="None"
IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
RefreshControlColor="Green"
RefreshCommand="{Binding RefreshCommand}">
<!---->
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:ExpenseReport">
<ViewCell>
<Grid Padding="10">
<Frame CornerRadius="20" HasShadow="True">
<StackLayout Orientation="Horizontal">
<StackLayout Padding="20,0,0,0">
<StackLayout>
<Label Text="{Binding Reason}" FontSize="Medium" VerticalOptions="Center" TextColor="Green" />
</StackLayout>
<StackLayout>
<Label Text="{Binding Kilometers, StringFormat='{}{0}km'}" FontSize="Small" VerticalOptions="Center"/>
<Label Text="{Binding Date, StringFormat='{0:dd.MM.yyyy}'}" FontSize="Small" VerticalOptions="Center"/>
<Label Text="{Binding TripCost}" FontSize="Small" VerticalOptions="Center"/>
</StackLayout>
</StackLayout>
</StackLayout>
</Frame>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Viewmodel OverviewExpenseReportViewModel
public class OverviewExpenseReportViewModel : ViewModelBase
{
public ObservableRangeCollection<ExpenseReport> ExpenseReportCollection { get; set; }
public AsyncCommand RefreshCommand { get; }
public OverviewExpenseReportViewModel()
{
RefreshCommand = new AsyncCommand(Refresh);
}
async Task Refresh()
{
ExpenseReportCollection = new ObservableRangeCollection<ExpenseReport>();
DBConnection db = new DBConnection();
await Task.Delay(1500);
ExpenseReportCollection.Clear();
ExpenseReportCollection.AddRange(db.GetDataExpenseReport());
}
}
I have long asked our friend Google but I somehow do not get anywhere. At this point
ExpenseReport.AddRange(db.GetDataExpenseReport());
I get the error that System.NullReferenceException: 'Object reference not set to an instance of an object.'
Can anyone help me on how I manage to populate the ListView, I appreciate any answers!
Lastly, I switched everything to ObservableRangeCollection from the MvvmHelpers dependency. But I always get this error, something I am doing wrong.
2
Answers
you are declaring
ExpenseReport
but it will be null until you instantiate it
For this problem, you need to recheck the
data type
ofthe returned list
andthe object
included in the returned list.Suppose the returned type is
IList<object>
, then you castIList<object>
toList<ExpenseReport>
,just as follows:Suppose the type of returned Object(
OtherObject
) is not the same object(ExpenseReport
), you need to iterate through the returned list one by one and then convert the returned Object to objectExpenseReport
.