using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using trakker.Models; namespace trakker.Forms { public partial class TaskForm : Form { /// /// The task instance being edited by this form. /// private readonly trakker.Models.Task _task; /// /// Binding source that connects the task status to the form controls. /// private BindingSource? _status; /// /// Binding source that connects the task priority to the form controls. /// private BindingSource? _priority; /// /// Binding source that connects the task model to the form controls. /// private BindingSource bindingSource = new BindingSource(); /// /// Error provider used to display validation errors next to input controls. /// private ErrorProvider errorProvider = new ErrorProvider(); /// /// Initializes a new instance of the class bound to /// the provided . Sets up data bindings for all /// visible input controls and configures dialog button behavior. /// /// The instance to edit. Must not be null. /// The binding source for status values. Must not be null. /// The binding source for priority values. Must not be null. public TaskForm(trakker.Models.Task task, BindingSource status, BindingSource priority) { InitializeComponent(); _task = task ?? throw new ArgumentNullException(nameof(task)); _status = status ?? throw new ArgumentNullException(nameof(status)); _priority = priority ?? throw new ArgumentNullException(nameof(priority)); Text = "Task Details"; comboBoxStatus.DataSource = _status; comboBoxStatus.DisplayMember = "Display"; comboBoxStatus.ValueMember = "Value"; comboBoxPriority.DataSource = _priority; comboBoxPriority.DisplayMember = "Display"; comboBoxPriority.ValueMember = "Value"; dateTimePickerDueDate.Format = DateTimePickerFormat.Custom; dateTimePickerDueDate.CustomFormat = "yyyy-MM-dd"; // // Bind model properties to controls so the UI reflects and updates the model. bindingSource.DataSource = _task; textBoxTitle.DataBindings.Add("Text", bindingSource, "Title", true); richTextBoxDescription.DataBindings.Add("Text", bindingSource, "Description", true); dateTimePickerDueDate.DataBindings.Add("Value", bindingSource, "DueDate", true); textBoxHoursEst.DataBindings.Add("Text", bindingSource, "EstimatedHours", true); textBoxHoursActual.DataBindings.Add("Text", bindingSource, "ActualHours", true); textBoxRate.DataBindings.Add("Text", bindingSource, "HourlyRate", true); comboBoxStatus.DataBindings.Add("SelectedValue", bindingSource, "Status", true); comboBoxPriority.DataBindings.Add("SelectedValue", bindingSource, "Priority", true); // Configure dialog buttons and window behavior. buttonOkay.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; this.CancelButton = buttonCancel; this.StartPosition = FormStartPosition.CenterParent; } /// /// Gets the instance edited by the form. /// public trakker.Models.Task Task { get => _task; private set { } } /// /// Validates the Name field. If the name is empty or whitespace, an error is set /// on the and the event is canceled to prevent the /// form from closing. /// private void textBoxTitle_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if (string.IsNullOrWhiteSpace(textBoxTitle.Text)) { errorProvider.SetError(textBoxTitle, "Title is required."); errorProvider.SetIconAlignment(textBoxTitle, ErrorIconAlignment.MiddleRight); errorProvider.SetIconPadding(textBoxTitle, 2); e.Cancel = true; } else { errorProvider.SetError(textBoxTitle, ""); } } } }