C# and .net MAUI beginner here.
I am struggling with resolving the problem of Index being out of range when I delete the object in the SQLite database and create any new objects in replacement.
My app contains 2 Pages and 2 additional classes with the code behind.
The problem seems to be in the db_refresh on MainPage method where eachTerm count is not decreased compared to the termlist count causing Index to error out. Here is the error syntax:
System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')'
However, the proper number of buttons is being generated in the generateInterface method.
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public static List<Term> termList = new List<Term>();
public static string dbLocation = Path.Combine(FileSystem.AppDataDirectory, "MyData.db");
public MainPage()
{
File.Delete(dbLocation);
dbActions.initiateDbTables();
InitializeComponent();
db_refresh();
generateInterface();
}
protected override void OnAppearing()
{
AppShell.SetBackgroundColor(this, Color.FromRgb(0, 0, 0));
db_refresh();
generateInterface();
}
public static void db_refresh()
{
termList.Clear();
var dataBase = new SQLiteConnection(dbLocation);
var queriedTerm = dataBase.Query<Term>("SELECT * FROM Terms");
foreach (Term eachTerm in queriedTerm)
{
termList.Add(eachTerm);
}
}
public void generateInterface()
{
termView.Children.Clear();
foreach (Term myTerm in termList)
{
Button termNameButton = new Button
{
Text = myTerm.termName,
BackgroundColor = Colors.Green,
TextColor = Colors.White,
FontAttributes = FontAttributes.Bold,
};
termNameButton.Clicked += async (sender, e) =>
{
await Navigation.PushAsync(new TermPage(myTerm.termId));
};
termView.Children.Add(termNameButton);
}
Button termAddButton = new Button()
{
Text = "Add Term",
BackgroundColor = Colors.Black,
TextColor = Colors.White,
FontAttributes = FontAttributes.Bold,
};
termAddButton.Clicked += void (sender, args) => clickNewTerm();
termView.Children.Add(termAddButton);
}
public void clickNewTerm()
{
dbActions.addNewDbTerm();
generateInterface();
}
}
The delete Term method is located in the separated page (TermPage) accessed when I click on the Terms button in the MainScreen. Here is the code of the TermPage:
public Term currentTerm;
public SQLiteConnection dbConnect = new SQLiteConnection(MainPage.dbLocation);
public TermPage(int termId)
{
InitializeComponent();
ButtonAdd();
Term myTerm = MainPage.termList[termId - 1];
currentTerm = myTerm;
termName.Text = currentTerm.termName;
}
private void ButtonAdd()
{
Button deleteTermButton = new Button()
{
Text = "Delete Term",
BackgroundColor = Colors.Red,
FontAttributes = FontAttributes.Bold,
};
deleteTermButton.Clicked += void (sender, args) => actionDeleteTerm();
TermPageView.Children.Add(deleteTermButton);
}
public async void actionDeleteTerm()
{
dbConnect.Delete(currentTerm);
MainPage.db_refresh();
await Navigation.PopAsync();
}
Here is the class that adds a new Term:
public class dbActions
{
public static void initiateDbTables()
{
var dbLocation = Path.Combine(FileSystem.AppDataDirectory, "MyData.db");
var dbConnect = new SQLiteConnection(dbLocation);
dbConnect.CreateTable<Term>();
}
public static void addNewDbTerm()
{
var dbConnect = new SQLiteConnection(MainPage.dbLocation);
var dbQuery = dbConnect.Query<Term>($"SELECT * FROM Terms ORDER BY termId DESC LIMIT 1");
if (dbQuery.Count != 0)
{
Term topTerm = dbQuery.First();
string termName = "Term " + (topTerm.termId + 1).ToString();
Term newTerm = new Term(termName, DateTime.Now, DateTime.Now.AddDays(60));
dbConnect.Insert(newTerm);
MainPage.db_refresh();
}
else
{
Term newTerm = new Term("Term1", DateTime.Now, DateTime.Now.AddDays(60));
dbConnect.Insert(newTerm);
MainPage.db_refresh();
}
}
}
I tried to use termList.Clear() to refresh the Index, but I am not sure if that's the correct approach.
to retrieve an item by id from a list of objects, do this