Benutzer mit den meisten Antworten
SQLLite Datenbank zugriff

Frage
-
Hallo Community,
Ich habe folgendes Problem: In meiner App möchte ich eine lokale SQLLite Datenbank verwenden. Ich habe eine Klasse "Character" erstellt die als SQL Tabelle verwendet werden soll. Die Datensätze aus der Tabelle möchte ich gerne auf einer Page als Liste anzeigen "CharacterListPage", wenn noch keine Einträge da sind ist diese Liste eben leer.
Mit dem Button "Add" möchte ich eine Page "CharacterSheetPage" aufrufen, über die ich einen neuen Datensatz anlegen kann.
Wenn ich auf einen bestehenden Eintrag clicke soll sich natürlich auch die CharacterSheetPage öffnen, nur, dass ich hier eben keinen neuen Datensatz, sondern eben den ausgewählten bearbeiten kann.
Aktuell habe ich noch keine Einträge in dieser Tabelle und wenn ich nun auf "Add" klicke, stützt die App ab.
Entsprechende Dateien hänge ich gleich an.
Könnt ihr mir vielleicht helfen?
Antworten
-
Ändere bitte in deinem CharacterListViewModel
async Task ExecuteLoadCharacterCommand() { IsBusy = true; try { CharacterObservableCollection.Clear(); var items = await database.GetCharacterAsync(); if (items.Any()) { for each (var item in items) { CharacterObservableCollection.Add(item); } } //var characters = await CharacterDataStore.GetItemsAsync(true); //Character = await database.GetCharacterAsync(); //var characters = database.GetCharacterAsync(); //for each (var character in characters) //{ // Character.Add(character); //} } catch (Exception ex) { Debug.WriteLine(ex); } finally { IsBusy = false; } }
Entferne das Leerzeichen zwischen for each
public void OnAppearing() { IsBusy = true; SelectedCharacter = null; }
In der Datei CharacterListPage.xaml
Von
<CollectionView x:Name="CharactersListView" ItemsSource="{Binding CharacterCollectionView}" SelectionMode="Single">
Zu
<CollectionView x:Name="CharactersListView" ItemsSource="{Binding CharacterObservableCollection}" SelectionMode="Single">
Eine ObservableCollection ist eine List. Diese Liste wird jetzt gefüllt und an das Contoll CollectionView übergeben.
Vorher hast Du eine CollectionView (Controll) an eine CollectionView übergeben. In ein ViewModel kommen grundsätzlich keine Controlls rein. Theoretisch sollte man das ViewModel jederzeit auch mit einem anderen UI-Framework benutzen können. Deswegen kommen in dieses auch keine Elemente von Xamarin
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github- Als Antwort markiert Schosch93 Montag, 20. März 2023 18:44
Alle Antworten
-
Models.Character.cs:
using System; using System.Collections.Generic; using System.Text; using SQLite; using System.IO; namespace Mythandria.Models { public class Character { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string PlayerName { get; set; } public string CharacterName { get; set; } public int Force_ID { get; set; } } }
-
Models.Database.cs:
using System.Collections.Generic; using System.Threading.Tasks; using SQLite; namespace Mythandria.Models { public class Database { readonly SQLiteAsyncConnection _database; public Database(string dbPath) { _database = new SQLiteAsyncConnection(dbPath); _database.CreateTableAsync<Character>().Wait(); } public Task<List<Character>> GetCharacterAsync() { return _database.Table<Character>().ToListAsync(); } public async Task<Character> GetCharacterAsync(int id) { var character = await _database.Table<Character>().FirstOrDefaultAsync(p => p.Id == id); return character; } public Task<int> SaveCharacterAsync(Character character) { return _database.InsertAsync(character); } } }
-
CharacterListPage.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" x:Class="Mythandria.Views.CharacterListPage" Shell.PresentationMode="ModalAnimated" Title="{Binding Title}" xmlns:local="clr-namespace:Mythandria.ViewModels" xmlns:model="clr-namespace:Mythandria.Models" xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" x:Name="CharactersListPage"> <ContentPage.ToolbarItems> <ToolbarItem Text="Add" Command="{Binding AddCharacterCommand}" /> </ContentPage.ToolbarItems> <RefreshView x:DataType="local:CharacterListViewModel" Command="{Binding LoadCharacterCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}"> <CollectionView x:Name="CharactersListView" ItemsSource="{Binding Character}" SelectionMode="None"> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Padding="10" x:DataType="model:Character"> <Label Text="ID:" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" TextColor="Black" FontSize="12" /> <Entry Text="{Binding Id, Mode=TwoWay}" FontSize="12" /> <Label Text="Charaktername:" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" TextColor="Black" FontSize="12" /> <Entry Text="{Binding CharacterName, Mode=TwoWay}" FontSize="12"/> <Label Text="Palyername:" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" TextColor="Black" FontSize="13" /> <Entry Text="{Binding PlayerName, Mode=TwoWay}" FontSize="12"/> <StackLayout.GestureRecognizers> <TapGestureRecognizer NumberOfTapsRequired="1" Command="{Binding Source={RelativeSource AncestorType={x:Type local:CharacterListViewModel}}, Path=CharacterTapped}" CommandParameter="{Binding .}"> </TapGestureRecognizer> </StackLayout.GestureRecognizers> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </RefreshView > </ContentPage>
-
CharacterListPage.xaml.cs:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using Mythandria.Models; using Mythandria.ViewModels; using Mythandria.Views; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace Mythandria.Views { //[XamlCompilation(XamlCompilationOptions.Compile)] public partial class CharacterListPage : ContentPage { CharacterListViewModel _viewModel; public CharacterListPage() { InitializeComponent(); BindingContext = _viewModel = new CharacterListViewModel(); } protected override void OnAppearing() { base.OnAppearing(); _viewModel.OnAppearing(); } } }
-
Hallo Schosch93,
wohin führt den der Command AddCharacterCommand. Hast Du noch ein ViewModel? Schau dir diesen Link an:
Befehlsschnittstelle in Xamarin.Forms - Xamarin | Microsoft Learn
Der Support für Xamarin endet am 1.5.2024. Neue Apps damit anzufangen oder sich einzuarbeiten, macht wenig Sinn.
Offizielle Support-Richtlinie für Xamarin | .NET (microsoft.com)
Xamarin wird durch .NET MAUI ersetzt:
Was ist .NET MAUI? - .NET MAUI | Microsoft Learn
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
CharacterSheetPage.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" x:Class="Mythandria.Views.CharacterSheetPage" xmlns:vm="clr-namespace:Mythandria.ViewModels" Title="{Binding Title}" BackgroundColor="LightGray" xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" ios:Page.UseSafeArea="true"> <ContentPage.BindingContext> <vm:CharacterSheetViewModel /> </ContentPage.BindingContext> <ContentPage.Resources> <ResourceDictionary> <Color x:Key="Caption">#000000</Color> <Color x:Key="Text">#000000</Color> </ResourceDictionary> </ContentPage.Resources> <ContentPage.Content> <StackLayout> <Label Text="Spielername:" TextColor="{StaticResource Caption}" /> <Entry Placeholder="Spielername" Text="{Binding PlayerName, Mode=TwoWay}" TextColor="{StaticResource Text}" /> <Label Text="Charaktername:" TextColor="{StaticResource Caption}" /> <Entry Placeholder="Charaktername" Text="{Binding CharacterName, Mode=TwoWay}" TextColor="{StaticResource Text}"/> <Label Text="" TextColor="{StaticResource Caption}" /> <Button Text="Speichern" /> </StackLayout> </ContentPage.Content> </ContentPage>
- Bearbeitet Schosch93 Dienstag, 14. März 2023 22:01
-
CharacterSheetPage.xaml.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SQLite; using Xamarin.Forms; using Xamarin.Forms.Xaml; using Mythandria.Models; using Mythandria.ViewModels; namespace Mythandria.Views { //[XamlCompilation(XamlCompilationOptions.Compile)] public partial class CharacterSheetPage : ContentPage { public CharacterSheetPage() { InitializeComponent(); BindingContext = new CharacterSheetViewModel(); } } }
-
Setze mal ein Breakpoint bei await Shell.Current.GoToAsync(nameof(CharacterSheetPage));
Wird der Code erreicht?
Funktioniert die Navigation schon an einer anderen Stelle mit Shell?
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
CharacterListViewModel.cs:
private Character _selectedCharacter; public ObservableCollection<Character> Character { get; } public Command LoadCharacterCommand { get; } public Command AddCharacterCommand { get; } public Command<Character> CharacterTapped { get; } public CharacterListViewModel() { Title = "Charakter"; Character = new ObservableCollection<Character>(); LoadCharacterCommand = new Command(async () => await ExecuteLoadCharacterCommand()); CharacterTapped = new Command<Character>(OnCharacterSelected); AddCharacterCommand = new Command(OnAddCharacter); } async Task ExecuteLoadCharacterCommand() {
IsBusy = true;
try
{
Character.Clear();
var characters = await CharacterDataStore.GetItemsAsync(true);
for each (var character in characters)
{
Character.Add(character);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}}
public Character SelectedCharacter {
get => _selectedCharacter;
set
{
SetProperty(ref _selectedCharacter, value);
OnCharacterSelected(value);
}} private async void OnAddCharacter(object obj) { await Shell.Current.GoToAsync(nameof(CharacterSheetPage)); } async void OnCharacterSelected(Character character) {
if (character == null)
return;
await Shell.Current.GoToAsync($"{nameof(CharacterSheetPage)}?{nameof(CharacterSheetViewModel.CharacterId)}={character.Id}");}
- Bearbeitet Schosch93 Dienstag, 14. März 2023 23:13
-
CharacterSheetViewModel.cs:
using System; using System.Windows.Input; using System.Collections.Generic; using System.Text; using System; using Xamarin.Essentials; using Xamarin.Forms; using System.Threading.Tasks; using System.Diagnostics; using Mythandria.Models; using SQLite; using System.Windows.Input; namespace Mythandria.ViewModels { [QueryProperty(nameof(CharacterId), nameof(CharacterId))] public class CharacterSheetViewModel : BaseViewModel { private int characterId; private string characterName; private string playerName; private int forceId; public CharacterSheetViewModel() { Title = "Charakterbogen"; SaveCommand = new Command(OnSave, ValidateSave); CancelCommand = new Command(OnCancel); this.PropertyChanged += (_, __) => SaveCommand.ChangeCanExecute(); } private bool ValidateSave() { return !String.IsNullOrWhiteSpace(playerName) && !String.IsNullOrWhiteSpace(characterName); } public string Id { get; set; } public string CharacterName { get => characterName; set => SetProperty(ref characterName, value); } public string PlayerName { get => playerName; set => SetProperty(ref playerName, value); } public int ForceId { get => forceId; set => SetProperty(ref forceId, value); } public int CharacterId { get { return characterId; } set { characterId = value; LoadCharacterId(value); } } public Command SaveCommand { get; } public Command CancelCommand { get; } private async void OnCancel() { // This will pop the current page off the navigation stack await Shell.Current.GoToAsync(".."); } private async void OnSave() { Character newCharacter = new Character() { Id = Convert.ToInt32( Guid.NewGuid().ToString()), CharacterName = CharacterName, PlayerName = PlayerName }; await CharacterDataStore.AddItemAsync(newCharacter); // This will pop the current page off the navigation stack await Shell.Current.GoToAsync(".."); } public async void LoadCharacterId(int characterId) { try { var character = await CharacterDataStore.GetItemAsync(characterId.ToString()); Id = character.Id.ToString(); CharacterName = character.CharacterName; PlayerName = character.PlayerName; ForceId = character.Force_ID; } catch (Exception) { Debug.WriteLine("Failed to Load Character"); } } } }
-
Irgendwas scheint der nicht an dem ExecuteLoadCharacterCommand() nicht zu mögen, sobald der im angehängten Code ist, will der die Nachricht nicht senden:
async Task ExecuteLoadCharacterCommand()
{
IsBusy = true;
try
{
Character.Clear();
var characters = await CharacterDataStore.GetItemAsym(true);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
- Bearbeitet Schosch93 Dienstag, 14. März 2023 22:09
-
Nach dem Befehl "var characters = await CharacterDataStore.GetItemsAsync(true);" innerhalb des Try-Blocks kommt noch eine foreach-schleife die den Befehl "Character.Add(character);" ausführt.
aber die will das Forum mich nicht posten lassen. Keine ahnung wieso...- Bearbeitet Schosch93 Dienstag, 14. März 2023 22:18
-
Ich habe grade dein anderen Thread gelesen wenn es sich eh um eine neue App handelt könntest Du sie mir auch zur Verfügung stellen dann schaue ich sie mir an.
Das Formum hat aktuell mit dem Wort for each ein problem wenn es zusammen geschrieben ist. Mach einfach ein Leerzeichen dann geht es.
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
Ja, der Debugger hält dort auch an.
Aber beim nächsten Prozedurschritt (also noch in der Zeile "await Shell.Current.GoToAsync(nameof(CharacterSheetPage));") fliegt der mit folgender Meldung raus:
System.ArgumentException: "unable to figure out route for: CharacterSheetPage
Arg_ParamName_Name" -
Z.B. über Github oder OneDrive, DropBox.
Hast Du schon nach der Fehlermeldung gesucht? Hilft z.B. das:
c# - Bug? System.ArgumentException: 'unable to figure out route for: - Stack Overflow
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
Ja das hat geholfen.
Ich habe in der AppShell.xaml.cs ein Routing für die CharacterSheetPage hinterlegt und nun öffnet sich die Page auch ganz normal, wenn ich auf den Add Button clicke.
Nur speichert der den Eintrag nicht.
Irgendwas mache ich da noch falsch, ich vermute den Fehler im CharacterSheetViewModel, aber sicher bin ich mir nicht.
-
Ich habe in meinem CharacterSheetViewModelldie funktion "OnSave"
Da springt der rein, wenn ich versuche meinen Eintrag zu speichern:
private async void OnSave() { if (isNewCharacter) { Character newCharacter = new Character() { Id = Guid.NewGuid().ToString(), CharacterName = CharacterName, PlayerName = PlayerName }; await CharacterDataStore.AddItemAsync(newCharacter); // This will pop the current page off the navigation stack await Shell.Current.GoToAsync(".."); } }
In der Zeileawait CharacterDataStore.AddItemAsync(newCharacter);
fliegt der dann raus.
Meldung:
System.NullReferenceException: "Object reference not set to an instance of an object."
Wie sage ich dem jetzt, dass der die Daten aus newCharacter als neuen Datensatz in die Tabelle Character einfügt? -
IDataStore.cs
using System; using System.Collections.Generic; using System.Threading.Tasks; namespace Mythandria.Services { public interface IDataStore<T> { Task<bool> AddItemAsync(T item); Task<bool> UpdateItemAsync(T item); Task<bool> DeleteItemAsync(string id); Task<T> GetItemAsync(string id); Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false); } }
-
BaseViewModel.cs:
using Mythandria.Models; using Mythandria.Services; using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using Xamarin.Forms; namespace Mythandria.ViewModels { public class BaseViewModel : INotifyPropertyChanged { public IDataStore<Item> ItemDataStore => DependencyService.Get<IDataStore<Item>>(); public IDataStore<Character> CharacterDataStore => DependencyService.Get<IDataStore<Character>>(); bool isBusy = false; public bool IsBusy { get { return isBusy; } set { SetProperty(ref isBusy, value); } } string title = string.Empty; public string Title { get { return title; } set { SetProperty(ref title, value); } } protected bool SetProperty<T>(ref T backingStore, T value, [CallerMemberName] string propertyName = "", Action onChanged = null) { if (EqualityComparer<T>.Default.Equals(backingStore, value)) return false; backingStore = value; onChanged?.Invoke(); OnPropertyChanged(propertyName); return true; } #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { var changed = PropertyChanged; if (changed == null) return; changed.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion } }
-
Wo ist den die Implementierung des Interfaces? Die Fehlermeldung sag ja ganz klar das eins von CharacterDataStore.AddItemAsync NULL ist.
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
habe das ein klein wenig umgeschrieben. Ich weiß zwar nicht ob der die Datensätze nun wirklich speichert, aber zumindest wirft er keinen Fehler mehr aus und kehrt auch zur CharacterListPage zurück nachdem man auf Save geklickt hat.
Hier wird aber immer noch kein Datensatz angezeigt.
Ich denke ich habe hier noch einen Fehler.
Bei initialisieren der Page läuft der durch folgenden Code:
async Task ExecuteLoadCharacterCommand() { Database database = new Database(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "mythandria_db.db3")); IsBusy = true; try { Character.Clear(); //var characters = await CharacterDataStore.GetItemsAsync(true); //Character = database.GetCharacterAsync(); var characters = database.GetCharacterAsync(); //for each (var character in characters) //{ // Character.Add(character); //} } catch (Exception ex) { Debug.WriteLine(ex); } finally { IsBusy = false; } }
Wenn ich das richtig verstanden habe soll der sich mit der Befehl
var characters = database.GetCharacterAsync();
Wenn ich das richtig verstanden habe soll der sich mit der Befehl eine Liste in die Variable characters laden. Wie kann ich diese List nun in meiner Page anzeigen?
- Bearbeitet Schosch93 Mittwoch, 15. März 2023 15:09
-
In deinem CharacterListViewModel gibt es eine ObservableCollection<Character> dort müssen die Daten aus der DB rein.
Um in die DB mal reinzuschauen kannst Du den DB Browser for SQLite (sqlitebrowser.org) benutzen.
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
Ich habe mal in die DB reingeschaut. Die Daten werden wie gewünscht gespeichert.
Jetzt muss ich die nur noch irgendwie in die ObservableCollection bekommen.
Ich habe das mal mit
var characters = database.GetCharacterAsync(); for each (var character in characters) { Charcter.add(charater); }
versucht, aber das will der nicht annehmen.
In meiner Databaseklasse steht folgended:
public Task<List<Character>> GetCharacterAsync() { return _database.Table<Character>().ToListAsync(); }
Sollte der mir so nicht eine Liste ausspucken, die ich mit for each durchlaufen kann?
Edit:
Ich habe nun eine CollectionView erstellt in die ich meine Charakter mit
CharacterCollectionView.ItemsSource = await database.GetCharacterAsync();
einlesen konnte.
Als nächsten gucke ich wie ich die CollectionView nun auf meiner CharacterList.xaml anzeigen lasse.- Bearbeitet Schosch93 Donnerstag, 16. März 2023 10:50
-
Nachdem ich hier noch ein
CharacterCollectionView= new CollectionView(); hinzugefügt hat, wird zumindest der Debugger keinen Fehler mehr.
Allerdings wird mir immer noch nichts angezeigt. Die Page bleibt leer.
Über den Debugger konnte ich sehen, dass meine CollectionView auch tatsächlich gefüllt wird
Hier ist meine CharakterListPage.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" x:Class="Mythandria.Views.CharacterListPage" Shell.PresentationMode="ModalAnimated" Title="{Binding Title}" xmlns:local="clr-namespace:Mythandria.ViewModels" xmlns:model="clr-namespace:Mythandria.Models" xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" x:Name="CharactersListPage"> <ContentPage.Resources> <!-- Define a visual state for the Selected state of the CollectionView --> <Style TargetType="StackLayout"> <Setter Property="VisualStateManager.VisualStateGroups"> <VisualStateGroupList> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal" /> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightGray" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </Setter> </Style> </ContentPage.Resources> <ContentPage.ToolbarItems> <ToolbarItem Text="Add" Command="{Binding AddCharacterCommand}" /> </ContentPage.ToolbarItems> <RefreshView x:DataType="local:CharacterListViewModel" Command="{Binding LoadCharacterCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}"> <CollectionView x:Name="CharactersListView" ItemsSource="{Binding CharacterCollectionView}" SelectionMode="None"> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Padding="10" x:DataType="model:Character"> <Label Text="ID:" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" TextColor="Black" FontSize="12" /> <Entry Text="{Binding Id, Mode=TwoWay}" FontSize="12" /> <Label Text="Charaktername:" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" TextColor="Black" FontSize="12" /> <Entry Text="{Binding CharacterName, Mode=TwoWay}" FontSize="12"/> <Label Text="Palyername:" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" TextColor="Black" FontSize="13" /> <Entry Text="{Binding PlayerName, Mode=TwoWay}" FontSize="12"/> <StackLayout.GestureRecognizers> <TapGestureRecognizer NumberOfTapsRequired="1" Command="{Binding Source={RelativeSource AncestorType={x:Type local:CharacterListViewModel}}, Path=CharacterTapped}" CommandParameter="{Binding .}"> </TapGestureRecognizer> </StackLayout.GestureRecognizers> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </RefreshView > </ContentPage>
Wieso wird meine CollectionView nicht auf der Page angezeigt?- Bearbeitet Schosch93 Sonntag, 19. März 2023 10:55
-
Das kann ich dir nicht sagen für mich sieht das richtig aus außer CommandParameter="{Binding .}". Aber ich kann nicht wissen ob alle Funktionen und Modele in deiner App wirklich verfügbar sind.
Ich würde dir empfehlen klein anzufangen und nach und nach die App zu erweitern. Scheinbar kopierst Du dir aus irgendwelchen Beispiel Apps den Code ohne ihn zu verstehen.
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github -
Das ist korrekt. Ich kopiere mir den Code aus Beispielen die ich im Internet finde und glaube, dass sie meinem Zweck dienlich sind und versuche ihn zu verstehen. So taste ich mich langsam an mein gewünschtes Ergebnis ran.
Step 1: Lauffähige App erstellen (Check)
Step 2: SQL Lite Datenbank erstellen (Check)
Step 3: Daten in Datenbank speichern (Check)
Step 4: gespeicherte Daten auslesen (Check)
Bis hier hin habe ich nun grob verstanden was der Code aus den Beispielen der bei mir bereits funktioniert macht. Der Code der noch nicht funktioniert ist der Teil den ich noch nicht verstehe, und wo ich Probleme habe entsprechende Erklärungen aus dem Internet zu beziehen.
Step 5: ausgelesene Daten anzeigen (in Progress)
Step 6: Angezeigte Daten zur weiteren Verarbeitung verwenden (ausstehend)
Ich habe den Tag <StackLayout.GestureRecognizers> auskommentiert. Der gehört ja eher zu Step 6. Der soll ja eigentlich später nur dazu führen, dass der Code aus meinem ViewModel ausgeführt wird, der ausgeführt werden soll, wenn eine der angezeigten Datensätze angeklickt/angetapped wird. Aber darüber mache ich mir Gedanken, wenn das anzeigen funktioniert.
Du sagst ja das das bisher so korrekt aussieht. Heißt also der Fehler muss ja irgendwo anders liegen. Daher habe ich nun auf deinen Vorschlag hin das Projekt gezippe und in die Dropbox hochgeladen.
hier der Link zur Zip:
https://www.dropbox.com/s/608v6mq6lr9bmw8/Mythandria.zip?dl=0
Ich habe noch nie was per DB freigegeben, daher hoffe ich dass das mit dem Link funktioniert ^^
Vielleicht kannst du ja mal drüber gucken :)
Wenn das erstmal so mit einer Tabelle funktioniert, will ich das später noch um weitere Tabellen erweitern um das Prinzip zu verinnerlichen.
Anschließend möchte ich abhängigkeiten verwenden (Ein Charakter hat eine Macht "Tabelle Force"), so dass ich aus einer Auswahl von den Einträgen der Tabelle Force habe aus denen ich mir den PK in den FK der tabelle Charakter (Feld Force_Id.. wird noch nicht benutzt) schreiben kann. (1-n beziehung)
Anschließend möchte ich eine n-m beziehung mit Abilities realisieren.. aber soweit bin ich ja noch laaaange nicht. Erstmal sollen die CRUD Funktionen mit einer Tabelle funktionieren. C (Create) habe ich schon;
R (Reed bin ich ja hier grade dabei); U (Update) ist auf Grund der Beispiele bereits teilweise vorhanden, aber das habe ich noch nicht getestet und ich glaube auch nicht dass das aktuell schon funktioniert, hier muss ich noch ein paar sachen verstehen. Und D (Delete) fehlt noch völlig, sollte aber glaube ich nicht soo schwer werden, wenn die anderen Sachen erstmal klappen. Aber wie gesagt: Schritt für Schritt :)- Bearbeitet Schosch93 Sonntag, 19. März 2023 19:05
-
-
Ändere bitte in deinem CharacterListViewModel
async Task ExecuteLoadCharacterCommand() { IsBusy = true; try { CharacterObservableCollection.Clear(); var items = await database.GetCharacterAsync(); if (items.Any()) { for each (var item in items) { CharacterObservableCollection.Add(item); } } //var characters = await CharacterDataStore.GetItemsAsync(true); //Character = await database.GetCharacterAsync(); //var characters = database.GetCharacterAsync(); //for each (var character in characters) //{ // Character.Add(character); //} } catch (Exception ex) { Debug.WriteLine(ex); } finally { IsBusy = false; } }
Entferne das Leerzeichen zwischen for each
public void OnAppearing() { IsBusy = true; SelectedCharacter = null; }
In der Datei CharacterListPage.xaml
Von
<CollectionView x:Name="CharactersListView" ItemsSource="{Binding CharacterCollectionView}" SelectionMode="Single">
Zu
<CollectionView x:Name="CharactersListView" ItemsSource="{Binding CharacterObservableCollection}" SelectionMode="Single">
Eine ObservableCollection ist eine List. Diese Liste wird jetzt gefüllt und an das Contoll CollectionView übergeben.
Vorher hast Du eine CollectionView (Controll) an eine CollectionView übergeben. In ein ViewModel kommen grundsätzlich keine Controlls rein. Theoretisch sollte man das ViewModel jederzeit auch mit einem anderen UI-Framework benutzen können. Deswegen kommen in dieses auch keine Elemente von Xamarin
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github- Als Antwort markiert Schosch93 Montag, 20. März 2023 18:44
-
Perfekt! Es klappt alles so wie es soll.
VIELEN VIELEN DANK!!!!
Die Update- und Delete-Funktionalität hat nun auch fast auf Anhieb funktioniert.
Auf der Grundlage kann ich auf jedenfall weiterarbeiten.
Da der Datenbankzugriff ja nun funktioniert, markiere ich diesen Thread mal als gelöst. Wenn ich irgendwo nicht weiterkomme, mache ich dafür dann einen separaten Thread auf (Vorrausgesetzt ich habe über Googel nichts finden können) -
Für Spiele Entwicklung bietet sich Unity Real-Time Development Platform | 3D, 2D, VR & AR Engine an. Dabei wird auch C# verwendet
Gruß Thomas
Der Junior lernt täglich, um Senior zu werden.
Der Senior lernt täglich, da er weiß, dass er immer Junior bleiben wird.
Github