From 160352383a30e776d9d6e1bfe670245056cf9cb2 Mon Sep 17 00:00:00 2001 From: Frozd Date: Mon, 23 Feb 2026 17:35:49 +0100 Subject: [PATCH] feat: set & get validation --- CarManagerV3/Car.cs | 76 ++++++++++++++++++++--- CarManagerV3/CarDetailsForm.Designer.cs | 3 + CarManagerV3/CarDetailsForm.cs | 80 +++++++++++++++++++++++-- CarManagerV3/ImageManager.cs | 10 +++- CarManagerV3/MainForm.Designer.cs | 21 +++---- 5 files changed, 165 insertions(+), 25 deletions(-) diff --git a/CarManagerV3/Car.cs b/CarManagerV3/Car.cs index 86770e7..c4a7667 100644 --- a/CarManagerV3/Car.cs +++ b/CarManagerV3/Car.cs @@ -11,14 +11,73 @@ namespace CarManagerV3 /// public class Car { - public int Id; - public string Make; - public string Model; - public int Year; - public string Color; - public int Mileage; - public decimal Price; - public int Order; + private int id; + private string make; + private string model; + private int year; + private string color; + private int mileage; + private decimal price; + private int order; + + public int Id { get => id; + set { + if (value < 0) throw new ArgumentException("Id cannot be negative."); + id = value; + } + } + + public string Make { get => make; + set + { + if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Make cannot be empty."); + make = value; + } + } + + public string Model { get => model; + set + { + if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Model cannot be empty."); + model = value; + } + } + + public int Year { get => year; + set + { + + if (value < 1886 || value > DateTime.Now.Year + 1) throw new ArgumentException("Year must be between 1886 and next year."); + Console.WriteLine($"Updating year to {year}"); + year = value; + } + } + + public string Color { get => color; + set + { + if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Color cannot be empty."); + color = value; + } + } + + public int Mileage { get => mileage; + set + { + if (value < 0) throw new ArgumentException("Mileage cannot be negative."); + mileage = value; + } + } + + public decimal Price { get => price; + set + { + if (value < 0) throw new ArgumentException("Price cannot be negative."); + price = value; + } + } + + public int Order { get => order; set => order = value; } //TODO: Make Id read-only CUID. Allows for better integrity, especially when merging. //TODO: Add buying price and automatic calculation of profit/loss with selling price suggestion. @@ -38,6 +97,7 @@ namespace CarManagerV3 /// The order. public Car(int id, string make, string model, int year, string color, int mileage, decimal price, int order = 0) { + // Sets the properties using the setters to ensure validation is applied. this.Id = id; this.Make = make; this.Model = model; diff --git a/CarManagerV3/CarDetailsForm.Designer.cs b/CarManagerV3/CarDetailsForm.Designer.cs index 9e94da0..a2e7c2a 100644 --- a/CarManagerV3/CarDetailsForm.Designer.cs +++ b/CarManagerV3/CarDetailsForm.Designer.cs @@ -120,6 +120,7 @@ this.tbxMake.Size = new System.Drawing.Size(473, 22); this.tbxMake.TabIndex = 1; this.tbxMake.TextChanged += new System.EventHandler(this.tbxMake_TextChanged); + this.tbxMake.Leave += new System.EventHandler(this.tbxMake_Leave); // // label2 // @@ -138,6 +139,7 @@ this.tbxModel.Size = new System.Drawing.Size(473, 22); this.tbxModel.TabIndex = 2; this.tbxModel.TextChanged += new System.EventHandler(this.tbxModel_TextChanged); + this.tbxModel.Leave += new System.EventHandler(this.tbxModel_Leave); // // label3 // @@ -239,6 +241,7 @@ this.tbxColor.Size = new System.Drawing.Size(473, 22); this.tbxColor.TabIndex = 4; this.tbxColor.TextChanged += new System.EventHandler(this.tbxColor_TextChanged); + this.tbxColor.Leave += new System.EventHandler(this.tbxColor_Leave); // // nudMileage // diff --git a/CarManagerV3/CarDetailsForm.cs b/CarManagerV3/CarDetailsForm.cs index c7278f2..5661b1b 100644 --- a/CarManagerV3/CarDetailsForm.cs +++ b/CarManagerV3/CarDetailsForm.cs @@ -29,34 +29,85 @@ namespace CarManagerV3 lblID.Text = $"ID: {car.Id}"; } + /// + /// Updates a car property safely by executing the update action and reverting it if an exception occurs. + /// + /// The update action. + /// The action to perform when the update fails. + private void SafeUpdate(Action updateAction, Action revertAction) + { + try + { + updateAction(); + } + catch (ArgumentException ex) + { + MessageBox.Show(ex.Message, "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Error); + revertAction(); + } + } + + //private string ValueOrFormer(string newValue, string oldValue) + //{ + // return string.IsNullOrWhiteSpace(newValue) ? oldValue : newValue; + //} + + private T ValueOrFormer(T newValue, T oldValue) + { + if (newValue is string str) + { + return string.IsNullOrWhiteSpace(str) ? oldValue : newValue; + } + return newValue; + } + private void tbxMake_TextChanged(object sender, EventArgs e) { - car.Make = tbxMake.Text; + SafeUpdate( + () => car.Make = ValueOrFormer(tbxMake.Text, car.Make), + () => tbxMake.Text = car.Make + ); } private void tbxModel_TextChanged(object sender, EventArgs e) { - car.Model = tbxModel.Text; + SafeUpdate( + () => car.Model = ValueOrFormer(tbxModel.Text, car.Model), + () => tbxModel.Text = car.Model + ); } private void nudYear_ValueChanged(object sender, EventArgs e) { - car.Year = (int)nudYear.Value; + Console.WriteLine("Year value changed: " + nudYear.Value); + SafeUpdate( + () => car.Year = (int)ValueOrFormer(nudYear.Value, car.Year), + () => nudYear.Value = car.Year + ); } private void tbxColor_TextChanged(object sender, EventArgs e) { - car.Color = tbxColor.Text; + SafeUpdate( + () => car.Color = ValueOrFormer(tbxColor.Text, car.Color), + () => tbxColor.Text = car.Color + ); } private void nudMileage_ValueChanged(object sender, EventArgs e) { - car.Mileage = (int)nudMileage.Value; + SafeUpdate( + () => car.Mileage = (int)nudMileage.Value, + () => nudMileage.Value = car.Mileage + ); } private void nudPrice_ValueChanged(object sender, EventArgs e) { - car.Price = nudPrice.Value; + SafeUpdate( + () => car.Price = nudPrice.Value, + () => nudPrice.Value = car.Price + ); } private async void btnSave_Click(object sender, EventArgs e) @@ -113,5 +164,22 @@ namespace CarManagerV3 } return base.ProcessCmdKey(ref msg, keyData); } + + private void tbxMake_Leave(object sender, EventArgs e) + { + tbxMake.Text = ValueOrFormer(tbxMake.Text, car.Make); + } + + private void tbxModel_Leave(object sender, EventArgs e) + { + tbxModel.Text = ValueOrFormer(tbxModel.Text, car.Model); + } + + private void tbxColor_Leave(object sender, EventArgs e) + { + tbxColor.Text = ValueOrFormer(tbxColor.Text, car.Color); + } + + } } diff --git a/CarManagerV3/ImageManager.cs b/CarManagerV3/ImageManager.cs index d811396..fea5032 100644 --- a/CarManagerV3/ImageManager.cs +++ b/CarManagerV3/ImageManager.cs @@ -63,7 +63,15 @@ namespace CarManagerV3 { Console.Error.WriteLine($"Error loading image: {ex.Message}"); } - return Image.FromFile("images/no_image_available.png"); + try + { + return Image.FromFile("images/no_image_available.png"); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error loading fallback image: {ex.Message}"); + return null; + } } /// diff --git a/CarManagerV3/MainForm.Designer.cs b/CarManagerV3/MainForm.Designer.cs index b486e64..78f8250 100644 --- a/CarManagerV3/MainForm.Designer.cs +++ b/CarManagerV3/MainForm.Designer.cs @@ -70,7 +70,7 @@ this.flpCars.AutoScroll = true; this.flpCars.AutoScrollMargin = new System.Drawing.Size(0, 200); this.flpCars.Dock = System.Windows.Forms.DockStyle.Fill; - this.flpCars.Location = new System.Drawing.Point(3, 67); + this.flpCars.Location = new System.Drawing.Point(3, 71); this.flpCars.Name = "flpCars"; this.flpCars.Size = new System.Drawing.Size(796, 412); this.flpCars.TabIndex = 1; @@ -83,7 +83,7 @@ this.tableLayoutPanel2.Controls.Add(this.tbxSearch, 0, 0); this.tableLayoutPanel2.Controls.Add(this.btnNewCar, 1, 0); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 27); + this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 31); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 1; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); @@ -112,11 +112,12 @@ // // menuStrip1 // + this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Size = new System.Drawing.Size(802, 24); + this.menuStrip1.Size = new System.Drawing.Size(802, 28); this.menuStrip1.TabIndex = 3; this.menuStrip1.Text = "menuStrip1"; // @@ -130,48 +131,48 @@ this.recentFilesToolStripMenuItem, this.revealInFileExplorerToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; - this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Size = new System.Drawing.Size(46, 24); this.fileToolStripMenuItem.Text = "File"; // // openToolStripMenuItem // this.openToolStripMenuItem.Name = "openToolStripMenuItem"; - this.openToolStripMenuItem.Size = new System.Drawing.Size(187, 22); + this.openToolStripMenuItem.Size = new System.Drawing.Size(238, 26); this.openToolStripMenuItem.Text = "Open"; this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); // // saveToolStripMenuItem // this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; - this.saveToolStripMenuItem.Size = new System.Drawing.Size(187, 22); + this.saveToolStripMenuItem.Size = new System.Drawing.Size(238, 26); this.saveToolStripMenuItem.Text = "Save"; this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); // // saveAsToolStripMenuItem // this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem"; - this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(187, 22); + this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(238, 26); this.saveAsToolStripMenuItem.Text = "Save as"; this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click); // // importToolStripMenuItem // this.importToolStripMenuItem.Name = "importToolStripMenuItem"; - this.importToolStripMenuItem.Size = new System.Drawing.Size(187, 22); + this.importToolStripMenuItem.Size = new System.Drawing.Size(238, 26); this.importToolStripMenuItem.Text = "Import"; this.importToolStripMenuItem.Click += new System.EventHandler(this.importToolStripMenuItem_Click); // // recentFilesToolStripMenuItem // this.recentFilesToolStripMenuItem.Name = "recentFilesToolStripMenuItem"; - this.recentFilesToolStripMenuItem.Size = new System.Drawing.Size(187, 22); + this.recentFilesToolStripMenuItem.Size = new System.Drawing.Size(238, 26); this.recentFilesToolStripMenuItem.Text = "Recent Files"; this.recentFilesToolStripMenuItem.Click += new System.EventHandler(this.recentFilesToolStripMenuItem_Click); // // revealInFileExplorerToolStripMenuItem // this.revealInFileExplorerToolStripMenuItem.Name = "revealInFileExplorerToolStripMenuItem"; - this.revealInFileExplorerToolStripMenuItem.Size = new System.Drawing.Size(187, 22); + this.revealInFileExplorerToolStripMenuItem.Size = new System.Drawing.Size(238, 26); this.revealInFileExplorerToolStripMenuItem.Text = "Reveal in File Explorer"; this.revealInFileExplorerToolStripMenuItem.Click += new System.EventHandler(this.revealInFileExplorerToolStripMenuItem_Click); //