From 159c783bd688ff8a5c16820141db2781f614a492 Mon Sep 17 00:00:00 2001 From: younes elhaddoury <167001847+elhy17@users.noreply.github.com> Date: Sun, 31 Aug 2025 23:33:31 +0200 Subject: [PATCH] Loginfenster und deutsche Kommentare --- README.md | 15 +-- WpfApp4/App.xaml | 7 +- WpfApp4/App.xaml.cs | 11 +- WpfApp4/DatabaseService.cs | 200 +++++++++++++++++++++--------------- WpfApp4/Fahrzeug.cs | 127 +++++++++++++++++++---- WpfApp4/LoginWindow.xaml | 56 ++++++++++ WpfApp4/LoginWindow.xaml.cs | 32 ++++++ WpfApp4/MainWindow.xaml | 6 +- WpfApp4/MainWindow.xaml.cs | 85 +++++++++++---- WpfApp4/PdfService.cs | 124 +++++++++++----------- 10 files changed, 458 insertions(+), 205 deletions(-) create mode 100644 WpfApp4/LoginWindow.xaml create mode 100644 WpfApp4/LoginWindow.xaml.cs diff --git a/README.md b/README.md index a8d7089..a3420ce 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,19 @@ Dieses Projekt dient als einfache Verwaltung von Fahrzeugen für ein Autohaus. D 3. Projekt `WpfApp4.sln` mit Visual Studio öffnen und starten ## Funktionen +- Anmeldung mit Benutzer **admin** und Passwort **admin** - Fahrzeuge anlegen, bearbeiten, löschen und anzeigen (CRUD) -- Auswahl aus 30 Marken mit jeweils sechs Modellen +- Auswahl aus 40 Marken mit jeweils sechs Modellen - Suche und Filterung über ein DataGrid - Export eines ausgewählten Fahrzeugs als PDF ## Bedienung -1. Marke und Modell aus den Listen wählen -2. Fahrzeugdaten eingeben und **Hinzufügen** drücken -3. Eintrag auswählen und über **Bearbeiten** oder **Löschen** ändern -4. **Aktualisieren** lädt die Liste neu, **Alle anzeigen** setzt Filter zurück -5. **Als PDF speichern** erzeugt ein Informationsblatt +1. Nach dem Start mit den oben genannten Daten anmelden +2. Marke und Modell aus den Listen wählen +3. Fahrzeugdaten eingeben und **Hinzufügen** drücken +4. Eintrag auswählen und über **Bearbeiten** oder **Löschen** ändern +5. **Aktualisieren** lädt die Liste neu, **Alle anzeigen** setzt Filter zurück +6. **Als PDF speichern** erzeugt ein Informationsblatt ## Projektstruktur - `WpfApp4`: Benutzeroberfläche und Logik @@ -34,4 +36,3 @@ Dieses Projekt wurde im Rahmen einer Übung von **Younes**, **Saad** und **Ayman - **Younes** kümmerte sich um Datenbank und grundlegende Geschäftslogik. - **Saad** gestaltete die Oberfläche und implementierte den PDF-Export. - **Ayman** verfasste die Dokumentation und begleitete die Tests. - diff --git a/WpfApp4/App.xaml b/WpfApp4/App.xaml index eb57771..bac8ac7 100644 --- a/WpfApp4/App.xaml +++ b/WpfApp4/App.xaml @@ -1,8 +1,7 @@ - + StartupUri="LoginWindow.xaml"> - - \ No newline at end of file + diff --git a/WpfApp4/App.xaml.cs b/WpfApp4/App.xaml.cs index ba355bc..5b99ea0 100644 --- a/WpfApp4/App.xaml.cs +++ b/WpfApp4/App.xaml.cs @@ -1,12 +1,11 @@ -using System; +using System; using System.Windows; namespace FahrzeugVerwaltung { - public partial class App : Application { - // Startet Programm und meldet Fehler + // Richtet die globale Fehlerbehandlung ein protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); @@ -14,7 +13,7 @@ namespace FahrzeugVerwaltung DispatcherUnhandledException += App_UnbehandelteAusnahme; } - // Zeigt Fehler in Oberfläche + // Zeigt nicht abgefangene Fehler an private void App_UnbehandelteAusnahme(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { MessageBox.Show($"Ein unerwarteter Fehler ist aufgetreten:\n{e.Exception.Message}", @@ -22,11 +21,11 @@ namespace FahrzeugVerwaltung e.Handled = true; } - // Meldet kritische Ausnahmen + // Meldet schwere Ausnahmen private void Domain_UnbehandelteAusnahme(object sender, UnhandledExceptionEventArgs e) { MessageBox.Show($"Ein kritischer Fehler ist aufgetreten:\n{((Exception)e.ExceptionObject).Message}", "Kritischer Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } } -} \ No newline at end of file +} diff --git a/WpfApp4/DatabaseService.cs b/WpfApp4/DatabaseService.cs index 27081fd..72ca369 100644 --- a/WpfApp4/DatabaseService.cs +++ b/WpfApp4/DatabaseService.cs @@ -17,12 +17,13 @@ namespace FahrzeugVerwaltung ErstelleDatenbank(); } - // Erstellt Datenbank und Tabelle + // Legt Datenbank und Tabelle an private void ErstelleDatenbank() { - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = @" + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + { + connection.Open(); + string query = @" CREATE TABLE IF NOT EXISTS Fahrzeuge ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Marke TEXT NOT NULL, @@ -34,98 +35,118 @@ namespace FahrzeugVerwaltung Farbe TEXT NOT NULL, ErstelltAm DATETIME DEFAULT CURRENT_TIMESTAMP )"; - using var command = new SQLiteCommand(query, connection); - command.ExecuteNonQuery(); + using (SQLiteCommand command = new SQLiteCommand(query, connection)) + { + command.ExecuteNonQuery(); + } + } } - // Speichert Fahrzeug und gibt neue Id zurück + // Speichert ein Fahrzeug und liefert die Id public int SpeichereFahrzeug(Fahrzeug fahrzeug) { - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = @" + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + { + connection.Open(); + string query = @" INSERT INTO Fahrzeuge (Marke, Modell, Baujahr, Leistung, Kilometerstand, Kaufpreis, Farbe) VALUES (@Marke, @Modell, @Baujahr, @Leistung, @Kilometer, @Kaufpreis, @Farbe); SELECT last_insert_rowid();"; - using var command = new SQLiteCommand(query, connection); - command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); - command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); - command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); - command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); - command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand); - command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); - command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); - return Convert.ToInt32(command.ExecuteScalar()); + using (SQLiteCommand command = new SQLiteCommand(query, connection)) + { + command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); + command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); + command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); + command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); + command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand); + command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); + command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); + return Convert.ToInt32(command.ExecuteScalar()); + } + } } - // Lädt alle Fahrzeuge + // Liefert alle Fahrzeuge public List LadeAlleFahrzeuge() { - var fahrzeuge = new List(); - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = "SELECT * FROM Fahrzeuge ORDER BY Marke, Modell"; - using var command = new SQLiteCommand(query, connection); - using var reader = command.ExecuteReader(); - while (reader.Read()) + List fahrzeuge = new List(); + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) { - fahrzeuge.Add(new Fahrzeug + connection.Open(); + string query = "SELECT * FROM Fahrzeuge ORDER BY Marke, Modell"; + using (SQLiteCommand command = new SQLiteCommand(query, connection)) + using (SQLiteDataReader reader = command.ExecuteReader()) { - Id = Convert.ToInt32(reader["Id"]), - Marke = reader["Marke"].ToString(), - Modell = reader["Modell"].ToString(), - Baujahr = Convert.ToInt32(reader["Baujahr"]), - Leistung = Convert.ToInt32(reader["Leistung"]), - Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), - Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), - Farbe = reader["Farbe"].ToString() - }); + while (reader.Read()) + { + fahrzeuge.Add(new Fahrzeug + { + Id = Convert.ToInt32(reader["Id"]), + Marke = reader["Marke"].ToString(), + Modell = reader["Modell"].ToString(), + Baujahr = Convert.ToInt32(reader["Baujahr"]), + Leistung = Convert.ToInt32(reader["Leistung"]), + Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), + Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), + Farbe = reader["Farbe"].ToString() + }); + } + } } return fahrzeuge; } - // Sucht Fahrzeuge mit Text + // Sucht Fahrzeuge nach Text public List SucheFahrzeuge(string suchbegriff) { if (string.IsNullOrWhiteSpace(suchbegriff)) + { return LadeAlleFahrzeuge(); + } - var fahrzeuge = new List(); - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = @" + List fahrzeuge = new List(); + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + { + connection.Open(); + string query = @" SELECT * FROM Fahrzeuge WHERE Marke LIKE @S OR Modell LIKE @S OR Farbe LIKE @S OR CAST(Baujahr AS TEXT) LIKE @S ORDER BY Marke, Modell"; - using var command = new SQLiteCommand(query, connection); - command.Parameters.AddWithValue("@S", $"%{suchbegriff}%"); - using var reader = command.ExecuteReader(); - while (reader.Read()) - { - fahrzeuge.Add(new Fahrzeug + using (SQLiteCommand command = new SQLiteCommand(query, connection)) { - Id = Convert.ToInt32(reader["Id"]), - Marke = reader["Marke"].ToString(), - Modell = reader["Modell"].ToString(), - Baujahr = Convert.ToInt32(reader["Baujahr"]), - Leistung = Convert.ToInt32(reader["Leistung"]), - Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), - Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), - Farbe = reader["Farbe"].ToString() - }); + command.Parameters.AddWithValue("@S", $"%{suchbegriff}%"); + using (SQLiteDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + fahrzeuge.Add(new Fahrzeug + { + Id = Convert.ToInt32(reader["Id"]), + Marke = reader["Marke"].ToString(), + Modell = reader["Modell"].ToString(), + Baujahr = Convert.ToInt32(reader["Baujahr"]), + Leistung = Convert.ToInt32(reader["Leistung"]), + Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), + Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), + Farbe = reader["Farbe"].ToString() + }); + } + } + } } return fahrzeuge; } - // Aktualisiert Fahrzeug + // Aktualisiert ein Fahrzeug public bool AktualisiereFahrzeug(Fahrzeug fahrzeug) { - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = @" + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + { + connection.Open(); + string query = @" UPDATE Fahrzeuge SET Marke=@Marke, Modell=@Modell, @@ -135,37 +156,48 @@ namespace FahrzeugVerwaltung Kaufpreis=@Kaufpreis, Farbe=@Farbe WHERE Id=@Id"; - using var command = new SQLiteCommand(query, connection); - command.Parameters.AddWithValue("@Id", fahrzeug.Id); - command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); - command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); - command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); - command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); - command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand); - command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); - command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); - return command.ExecuteNonQuery() > 0; + using (SQLiteCommand command = new SQLiteCommand(query, connection)) + { + command.Parameters.AddWithValue("@Id", fahrzeug.Id); + command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); + command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); + command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); + command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); + command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand); + command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); + command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); + return command.ExecuteNonQuery() > 0; + } + } } - // Löscht Fahrzeug + // Löscht ein Fahrzeug public bool LoescheFahrzeug(int id) { - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = "DELETE FROM Fahrzeuge WHERE Id=@Id"; - using var command = new SQLiteCommand(query, connection); - command.Parameters.AddWithValue("@Id", id); - return command.ExecuteNonQuery() > 0; + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + { + connection.Open(); + string query = "DELETE FROM Fahrzeuge WHERE Id=@Id"; + using (SQLiteCommand command = new SQLiteCommand(query, connection)) + { + command.Parameters.AddWithValue("@Id", id); + return command.ExecuteNonQuery() > 0; + } + } } - // Zählt Fahrzeuge + // Zählt vorhandene Fahrzeuge public int HoleAnzahlFahrzeuge() { - using var connection = new SQLiteConnection(_connectionString); - connection.Open(); - string query = "SELECT COUNT(*) FROM Fahrzeuge"; - using var command = new SQLiteCommand(query, connection); - return Convert.ToInt32(command.ExecuteScalar()); + using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + { + connection.Open(); + string query = "SELECT COUNT(*) FROM Fahrzeuge"; + using (SQLiteCommand command = new SQLiteCommand(query, connection)) + { + return Convert.ToInt32(command.ExecuteScalar()); + } + } } } } diff --git a/WpfApp4/Fahrzeug.cs b/WpfApp4/Fahrzeug.cs index 3a10386..e500251 100644 --- a/WpfApp4/Fahrzeug.cs +++ b/WpfApp4/Fahrzeug.cs @@ -14,44 +14,128 @@ namespace FahrzeugVerwaltung private decimal _kaufpreis; private string _farbe; - public int Id { get => _id; set { _id = value; MeldeEigenschaft(nameof(Id)); } } - public string Marke { get => _marke; set { _marke = value; MeldeEigenschaft(nameof(Marke)); } } - public string Modell { get => _modell; set { _modell = value; MeldeEigenschaft(nameof(Modell)); } } - public int Baujahr { get => _baujahr; set { _baujahr = value; MeldeEigenschaft(nameof(Baujahr)); MeldeEigenschaft(nameof(AktuellerWert)); MeldeEigenschaft(nameof(AktuellerWertFormatiert)); } } - public int Leistung { get => _leistung; set { _leistung = value; MeldeEigenschaft(nameof(Leistung)); } } - public int Kilometerstand { get => _kilometerstand; set { _kilometerstand = value; MeldeEigenschaft(nameof(Kilometerstand)); MeldeEigenschaft(nameof(KilometerstandFormatiert)); MeldeEigenschaft(nameof(AktuellerWert)); MeldeEigenschaft(nameof(AktuellerWertFormatiert)); } } - public decimal Kaufpreis { get => _kaufpreis; set { _kaufpreis = value; MeldeEigenschaft(nameof(Kaufpreis)); MeldeEigenschaft(nameof(KaufpreisFormatiert)); MeldeEigenschaft(nameof(AktuellerWert)); MeldeEigenschaft(nameof(AktuellerWertFormatiert)); } } - public string Farbe { get => _farbe; set { _farbe = value; MeldeEigenschaft(nameof(Farbe)); } } + public int Id + { + get { return _id; } + set { _id = value; MeldeEigenschaft(nameof(Id)); } + } - public string KilometerstandFormatiert => $"{Kilometerstand:N0} km"; - public string KaufpreisFormatiert => $"{Kaufpreis:C}"; - public string AktuellerWertFormatiert => $"{AktuellerWert:C}"; + public string Marke + { + get { return _marke; } + set { _marke = value; MeldeEigenschaft(nameof(Marke)); } + } - // Geschätzter aktueller Wert - public decimal AktuellerWert => BerechneAktuellenWert(); + public string Modell + { + get { return _modell; } + set { _modell = value; MeldeEigenschaft(nameof(Modell)); } + } - // Berechnet aktuellen Wert + public int Baujahr + { + get { return _baujahr; } + set + { + _baujahr = value; + MeldeEigenschaft(nameof(Baujahr)); + MeldeEigenschaft(nameof(AktuellerWert)); + MeldeEigenschaft(nameof(AktuellerWertFormatiert)); + } + } + + public int Leistung + { + get { return _leistung; } + set { _leistung = value; MeldeEigenschaft(nameof(Leistung)); } + } + + public int Kilometerstand + { + get { return _kilometerstand; } + set + { + _kilometerstand = value; + MeldeEigenschaft(nameof(Kilometerstand)); + MeldeEigenschaft(nameof(KilometerstandFormatiert)); + MeldeEigenschaft(nameof(AktuellerWert)); + MeldeEigenschaft(nameof(AktuellerWertFormatiert)); + } + } + + public decimal Kaufpreis + { + get { return _kaufpreis; } + set + { + _kaufpreis = value; + MeldeEigenschaft(nameof(Kaufpreis)); + MeldeEigenschaft(nameof(KaufpreisFormatiert)); + MeldeEigenschaft(nameof(AktuellerWert)); + MeldeEigenschaft(nameof(AktuellerWertFormatiert)); + } + } + + public string Farbe + { + get { return _farbe; } + set { _farbe = value; MeldeEigenschaft(nameof(Farbe)); } + } + + public string KilometerstandFormatiert + { + get { return $"{Kilometerstand:N0} km"; } + } + + public string KaufpreisFormatiert + { + get { return $"{Kaufpreis:C}"; } + } + + public string AktuellerWertFormatiert + { + get { return $"{AktuellerWert:C}"; } + } + + // Berechneter aktueller Wert + public decimal AktuellerWert + { + get { return BerechneAktuellenWert(); } + } + + // Ermittelt einen Schätzwert public decimal BerechneAktuellenWert() { - if (Kaufpreis <= 0 || Baujahr <= 0) return 0; + if (Kaufpreis <= 0 || Baujahr <= 0) + { + return 0; + } int alter = DateTime.Now.Year - Baujahr; decimal wertverlust = 0; for (int i = 0; i < alter; i++) + { wertverlust += (i < 3) ? 0.15m : 0.10m; + } wertverlust += (Kilometerstand / 10000m) * 0.02m; - if (wertverlust > 0.90m) wertverlust = 0.90m; + if (wertverlust > 0.90m) + { + wertverlust = 0.90m; + } decimal wert = Kaufpreis * (1 - wertverlust); decimal mindestwert = Kaufpreis * 0.05m; - if (wert < mindestwert) wert = mindestwert; + if (wert < mindestwert) + { + wert = mindestwert; + } return Math.Round(wert, 2); } - // Beschreibung für Anzeige + // Text für die Oberfläche public string HoleBeschreibung() { return $"{Marke} {Modell} ({Baujahr}) - {Leistung} PS - {KilometerstandFormatiert} - {Farbe}"; @@ -71,12 +155,15 @@ namespace FahrzeugVerwaltung public event PropertyChangedEventHandler PropertyChanged; - // Meldet geänderte Eigenschaft + // Meldet geänderte Eigenschaften private void MeldeEigenschaft(string eigenschaft) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(eigenschaft)); } - public override string ToString() => $"{Marke} {Modell} ({Baujahr})"; + public override string ToString() + { + return $"{Marke} {Modell} ({Baujahr})"; + } } } diff --git a/WpfApp4/LoginWindow.xaml b/WpfApp4/LoginWindow.xaml new file mode 100644 index 0000000..23e92d8 --- /dev/null +++ b/WpfApp4/LoginWindow.xaml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + +