Home > Blockchain >  Xamarin - Fill ListView with MySql Data
Xamarin - Fill ListView with MySql Data

Time:12-08

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.

CodePudding user response:

you are declaring ExpenseReport

public ObservableRangeCollection<ExpenseReport> ExpenseReport { get; set; }
   

but it will be null until you instantiate it

ExpenseReport = new ObservableRangeCollection<ExpenseReport>();
   

CodePudding user response:

System.InvalidCastException: 'Specified cast is not valid.. Is something wrong with that Line? ExpenseReport.AddRange(db.GetDataExpenseReport());``

For this problem, you need to recheck the data type of the returned list and the object included in the returned list.

Suppose the returned type is IList<object>, then you cast IList<object> to List<ExpenseReport>,just as follows:

   //initialize variable `ExpenseReport` here
  ExpenseReportCollection = new ObservableRangeCollection<ExpenseReport>();

 //suppose `data` is the returned data list
 ExpenseReportCollection.AddRange(data as List<ExpenseReport>);

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 object ExpenseReport.

  • Related