Laden...

Wie kann ich eine ObservableCollection<T> aus einer SQLite Datenbank an ein ListViewControl binden?

Erstellt von CombatKarl vor 3 Jahren Letzter Beitrag vor 3 Jahren 771 Views
CombatKarl Themenstarter:in
36 Beiträge seit 2020
vor 3 Jahren
Wie kann ich eine ObservableCollection<T> aus einer SQLite Datenbank an ein ListViewControl binden?

Hallo zusammen,

anbei mein bisher im Testprojekt verwendeter Code.

Grundsätzlich ist der Plan diverse Textboxeinträge in einer SQLite Datenbank abzulegen und anschließend in einem ListViewControl auszugeben. Nur irgendwo hängt es bei mir in der Praxis.

Das Model


namespace SQLTest.Model
{
    public class Einsatz : ViewModelBase
    {
        private string _ersterString;
        private string _zweiterString;

        [PrimaryKey, AutoIncrement]
        public int ID { get; set; }
        public string ErsterString
        {
            get => this._ersterString;
            set => SetProperty(ref this._ersterString, value);
        }
        public string ZweiterString
        {
            get => this._zweiterString;
            set => SetProperty(ref this._zweiterString, value);
        }

    }
}

Das ViewModel


namespace SQLTest.ViewModel
{
    public class MainWindowViewModel : ViewModelBase
    {
        public Einsatz MyEinsatz { get; set; } = new Einsatz();
        public ObservableCollection<Einsatz> MyCollection { get; set; }
        public ICommand SaveToDataBaseCommand => new SaveToDataBaseCommand(this);
        public ICommand ReadFromDataBaseCommand => new ReadFromDataBaseCommand(this);

        public MainWindowViewModel()
        {

        }

    }
}

Das Command


namespace SQLTest.Commands
{
    public class ReadFromDataBaseCommand : ICommand
    {
        private MainWindowViewModel _viewmodel { get; set; }

        #region ICommand Members
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            MyReadDataBaseCommand(parameter);
        }
        #endregion

        public ReadFromDataBaseCommand(MainWindowViewModel viewmodel)
        {
            _viewmodel = viewmodel;
        }

        private void MyReadDataBaseCommand(object parameter)
        {
            
            using (SQLiteConnection cnn = new SQLiteConnection(App.databasePath))
            {
                cnn.CreateTable<Einsatz>();
                _viewmodel.MyEinsatz.ErsterString = cnn.Table<Einsatz>().First().ErsterString.ToString();
                _viewmodel.MyEinsatz.ZweiterString = cnn.Table<Einsatz>().First().ZweiterString.ToString();
                _viewmodel.MyCollection = new ObservableCollection<Einsatz>(cnn.Table<Einsatz>().ToList());
            }
        }

    }
}

Das MainWindow


<Window x:Class="SQLTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SQLTest"
        xmlns:viewModel="clr-namespace:SQLTest.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <viewModel:MainWindowViewModel x:Key="MyMainVM"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource MyMainVM}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0" Orientation="Vertical" VerticalAlignment="Top">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Erster String :" FontSize="15" Margin="10 10" Width="120"/>
                <TextBox FontSize="15" Width="200" Margin="40 10" Text="{Binding MyEinsatz.ErsterString ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Zweiter String :" FontSize="15" Margin="10 10" Width="120"/>
                <TextBox FontSize="15" Width="200" Margin="40 10" Text="{Binding MyEinsatz.ZweiterString,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            </StackPanel>
        </StackPanel>
        <StackPanel VerticalAlignment="Bottom">
            <StackPanel Orientation="Horizontal" Margin="10" HorizontalAlignment="Center">
                <Button Content="Save" FontSize="15" Width="100" Margin="10 0" Command="{Binding SaveToDataBaseCommand}"/>
                <Button Content="Load" FontSize="15" Width="100" Margin="10 0" Command="{Binding ReadFromDataBaseCommand}"/>
            </StackPanel>    
        </StackPanel>
        <ListView Grid.Column="1" Margin="10" ItemsSource="{Binding MyCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding ErsterString ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                    <GridViewColumn DisplayMemberBinding="{Binding ZweiterString ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

Auf den Button "Save" werden beide Einträge aus den Textboxen in die SQLite Datenbank übernommen.

Bei "Load" werden auch beide Textboxen wieder aus der Datenbank befüllt, nur leider bleibt mein Listview gänzlich leer. Die ObservableCollection zeigt auch den passenden Count für die Anzahl der Einträge der Datenbank an.

Was mache ich falsch oder wo hängt's ??

Vielen Dank für die Hilfe !

<--- Wer übt, ist feige ! --->

4.939 Beiträge seit 2008
vor 3 Jahren

Du triggerst bei MyCollection (in MainWindowViewModel) beim Setzen kein PropertyChanged und dadurch aktualisiert sich die ListView nicht.

Bei den beiden TextBoxen funktioniert es, da du dort ja kein neues Einsatz-Objekt erzeugst, sondern das bestehende änderst (und dessen Eigenschaften per SetProperty das PropertyChanged-Ereignis aufrufen).

CombatKarl Themenstarter:in
36 Beiträge seit 2020
vor 3 Jahren

Oh man...

da steht man direkt davor und sieht es dennoch nicht !!

Herzlichen dank 👍

<--- Wer übt, ist feige ! --->

16.832 Beiträge seit 2008
vor 3 Jahren

Ist das Absicht, dass Dein ViewModel zeitgleich Deine Datenbank-Entität ist?

Damit zwingst Du Dich selbst Logik in die UI zu packen.
=> [Artikel] Drei-Schichten-Architektur

CombatKarl Themenstarter:in
36 Beiträge seit 2020
vor 3 Jahren

Ich hab mir beim Erstellen des beispielhaften Codes darüber keine Gedanken gemacht, weil das nicht das Problem war. Grundsätzlich ist aber alles im Zusammenhang mit der Datenbank in eigene Klassen ausgelagert.

Aber danke für die Anmerkung.

<--- Wer übt, ist feige ! --->