diff --git a/MVPLearning.sln b/MVPLearning.sln new file mode 100644 index 0000000..8143007 --- /dev/null +++ b/MVPLearning.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34714.143 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MVPLearning", "MVPLearning\MVPLearning.csproj", "{90225EB5-197B-475B-9AB4-8E8D642EF4AE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {90225EB5-197B-475B-9AB4-8E8D642EF4AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90225EB5-197B-475B-9AB4-8E8D642EF4AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90225EB5-197B-475B-9AB4-8E8D642EF4AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90225EB5-197B-475B-9AB4-8E8D642EF4AE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7FEEDE7A-D909-42A2-A061-B95C22E81025} + EndGlobalSection +EndGlobal diff --git a/MVPLearning/BaseLibrary/BaseDateTimePicker.cs b/MVPLearning/BaseLibrary/BaseDateTimePicker.cs new file mode 100644 index 0000000..f222c0f --- /dev/null +++ b/MVPLearning/BaseLibrary/BaseDateTimePicker.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVPLearning.BaseLibrary +{ + // adapted from https://slapouttech.blogspot.com/2019/01/my-nullable-datetime-picker.html + public class BaseDateTimePicker : DateTimePicker + { + public DateTime? BoundValue { get; set; } + public BaseDateTimePicker() : base() + { + ShowCheckBox = true; + Format = DateTimePickerFormat.Custom; + } + public void Bind(object datasource, string dataproperty) + { + var oldBinding = this.DataBindings[nameof(BoundValue)]; + if (oldBinding != null) { DataBindings.Remove(oldBinding); } + + var newBinding = new Binding(nameof(BoundValue), datasource, dataproperty, true); + newBinding.Format += FormatMyDate; + newBinding.Parse += ParseMyDate; + DataBindings.Add(newBinding); + } + + private void FormatMyDate(object? sender, ConvertEventArgs e) + { + if (e.Value == null) + { + //Value = Value; + Format = DateTimePickerFormat.Custom; + CustomFormat = " "; + Checked = false; + } + else + { + Value = (DateTime)e.Value; + Format = DateTimePickerFormat.Custom; + CustomFormat = "MM/dd/yyyy"; + Checked = true; + } + } + private void ParseMyDate(object? sender, ConvertEventArgs e) + { + e.Value = Checked ? Value : null; + } + protected override void OnValueChanged(EventArgs eventargs) + { + System.Diagnostics.Debug.WriteLine("OnValueChanged"); + base.OnValueChanged(eventargs); + BoundValue = Value; + Format = DateTimePickerFormat.Custom; + CustomFormat = Checked ? "MM/dd/yyyy" : " "; + } + protected override void OnValidated(EventArgs e) + { + base.OnValidated(e); + } + protected override void OnValidating(CancelEventArgs e) + { + base.OnValidating(e); + System.Diagnostics.Debug.WriteLine("OnValidating"); + System.Diagnostics.Debug.WriteLine($"Value: {Value}"); + System.Diagnostics.Debug.WriteLine($"BoundValue: {BoundValue}"); + } + + } +} diff --git a/MVPLearning/BaseLibrary/BaseForm.cs b/MVPLearning/BaseLibrary/BaseForm.cs new file mode 100644 index 0000000..ad8e201 --- /dev/null +++ b/MVPLearning/BaseLibrary/BaseForm.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVPLearning.BaseLibrary +{ + public class BaseForm : Form + { + } +} diff --git a/MVPLearning/BaseLibrary/BaseTextBox.cs b/MVPLearning/BaseLibrary/BaseTextBox.cs new file mode 100644 index 0000000..5a7de1f --- /dev/null +++ b/MVPLearning/BaseLibrary/BaseTextBox.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVPLearning.BaseLibrary +{ + public class BaseTextBox : TextBox + { + public BaseTextBox() : base() + { + BorderStyle = BorderStyle.FixedSingle; + } + public void Bind(object datasource, string dataproperty) + { + var oldBinding = DataBindings[nameof(Text)]; + if (oldBinding != null) { DataBindings.Remove(oldBinding); } + + var newBinding = new Binding(nameof(Text), datasource, dataproperty, false); + DataBindings.Add(newBinding); + } + + protected override void OnGotFocus(EventArgs e) + { + base.OnGotFocus(e); + BackColor = Color.FromArgb(183, 219, 255); + } + protected override void OnLostFocus(EventArgs e) + { + base.OnLostFocus(e); + BackColor = Color.White; + } + } +} diff --git a/MVPLearning/MVPLearning.csproj b/MVPLearning/MVPLearning.csproj new file mode 100644 index 0000000..663fdb8 --- /dev/null +++ b/MVPLearning/MVPLearning.csproj @@ -0,0 +1,11 @@ + + + + WinExe + net8.0-windows + enable + true + enable + + + \ No newline at end of file diff --git a/MVPLearning/MainView.Designer.cs b/MVPLearning/MainView.Designer.cs new file mode 100644 index 0000000..e0f0636 --- /dev/null +++ b/MVPLearning/MainView.Designer.cs @@ -0,0 +1,109 @@ +namespace MVPLearning +{ + partial class MainView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + menuStrip1 = new MenuStrip(); + fileToolStripMenuItem = new ToolStripMenuItem(); + exitToolStripMenuItem = new ToolStripMenuItem(); + recordKeepingToolStripMenuItem = new ToolStripMenuItem(); + sermonFilerToolStripMenuItem = new ToolStripMenuItem(); + maintainSermonFilerToolStripMenuItem = new ToolStripMenuItem(); + menuStrip1.SuspendLayout(); + SuspendLayout(); + // + // menuStrip1 + // + menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, recordKeepingToolStripMenuItem }); + menuStrip1.Location = new Point(0, 0); + menuStrip1.Name = "menuStrip1"; + menuStrip1.Size = new Size(800, 24); + menuStrip1.TabIndex = 1; + menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { exitToolStripMenuItem }); + fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + fileToolStripMenuItem.Size = new Size(37, 20); + fileToolStripMenuItem.Text = "&File"; + // + // exitToolStripMenuItem + // + exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + exitToolStripMenuItem.Size = new Size(180, 22); + exitToolStripMenuItem.Text = "E&xit"; + exitToolStripMenuItem.Click += ExitToolStripMenuItem_Click; + // + // recordKeepingToolStripMenuItem + // + recordKeepingToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { sermonFilerToolStripMenuItem }); + recordKeepingToolStripMenuItem.Name = "recordKeepingToolStripMenuItem"; + recordKeepingToolStripMenuItem.Size = new Size(102, 20); + recordKeepingToolStripMenuItem.Text = "&Record Keeping"; + // + // sermonFilerToolStripMenuItem + // + sermonFilerToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { maintainSermonFilerToolStripMenuItem }); + sermonFilerToolStripMenuItem.Name = "sermonFilerToolStripMenuItem"; + sermonFilerToolStripMenuItem.Size = new Size(180, 22); + sermonFilerToolStripMenuItem.Text = "Sermon Filer"; + // + // maintainSermonFilerToolStripMenuItem + // + maintainSermonFilerToolStripMenuItem.Name = "maintainSermonFilerToolStripMenuItem"; + maintainSermonFilerToolStripMenuItem.Size = new Size(190, 22); + maintainSermonFilerToolStripMenuItem.Text = "Maintain Sermon Filer"; + maintainSermonFilerToolStripMenuItem.Click += MaintainSermonFilerToolStripMenuItem_Click; + // + // MainView + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(menuStrip1); + IsMdiContainer = true; + MainMenuStrip = menuStrip1; + Name = "MainView"; + Text = "MDI Window"; + menuStrip1.ResumeLayout(false); + menuStrip1.PerformLayout(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private MenuStrip menuStrip1; + private ToolStripMenuItem fileToolStripMenuItem; + private ToolStripMenuItem exitToolStripMenuItem; + private ToolStripMenuItem recordKeepingToolStripMenuItem; + private ToolStripMenuItem sermonFilerToolStripMenuItem; + private ToolStripMenuItem maintainSermonFilerToolStripMenuItem; + } +} diff --git a/MVPLearning/MainView.cs b/MVPLearning/MainView.cs new file mode 100644 index 0000000..cb83e50 --- /dev/null +++ b/MVPLearning/MainView.cs @@ -0,0 +1,20 @@ +namespace MVPLearning +{ + public partial class MainView : Form + { + public MainView() + { + InitializeComponent(); + } + + private void MaintainSermonFilerToolStripMenuItem_Click(object sender, EventArgs e) + { + + } + + private void ExitToolStripMenuItem_Click(object sender, EventArgs e) + { + Application.Exit(); + } + } +} diff --git a/MVPLearning/MainView.resx b/MVPLearning/MainView.resx new file mode 100644 index 0000000..a0623c8 --- /dev/null +++ b/MVPLearning/MainView.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/MVPLearning/Program.cs b/MVPLearning/Program.cs new file mode 100644 index 0000000..1deb5e9 --- /dev/null +++ b/MVPLearning/Program.cs @@ -0,0 +1,17 @@ +namespace MVPLearning +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new MainView()); + } + } +} \ No newline at end of file diff --git a/MVPLearning/RecordKeeping/SermonFiler/IMaintainSermonFilerView.cs b/MVPLearning/RecordKeeping/SermonFiler/IMaintainSermonFilerView.cs new file mode 100644 index 0000000..9f620d3 --- /dev/null +++ b/MVPLearning/RecordKeeping/SermonFiler/IMaintainSermonFilerView.cs @@ -0,0 +1,18 @@ +namespace MVPLearning.RecordKeeping.SermonFiler +{ + internal interface IMaintainSermonFilerView + { + void LoadData(MaintainSermonFilerModel model); + event EventHandler? AddButtonClicked; + event EventHandler? DeleteButtonClicked; + event EventHandler? LocateButtonClicked; + event EventHandler? NextButtonClicked; + event EventHandler? PreviousButtonClicked; + event EventHandler? CloseButtonClicked; + event EventHandler? BrowseButtonClicked; + event EventHandler? LaunchButtonClicked; + event EventHandler? SaveButtonClicked; + event EventHandler? CancelButtonClicked; + + } +} \ No newline at end of file diff --git a/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerModel.cs b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerModel.cs new file mode 100644 index 0000000..953826b --- /dev/null +++ b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerModel.cs @@ -0,0 +1,74 @@ +using MVPLearning.Structure; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVPLearning.RecordKeeping.SermonFiler +{ + internal class MaintainSermonFilerModel : ObservableObject + { + public int Seid { get; set; } + public string Title { get => _title; set => SetProperty(ref _title, value); } + private string _title = string.Empty; + public string Scripture { get => _scripture; set => SetProperty(ref _scripture, value); } + private string _scripture = string.Empty; + public DateTime? When { get => _when; set => SetProperty(ref _when, value); } + private DateTime? _when; + public string Subject { get => _subject; set => SetProperty(ref _subject, value); } + private string _subject = string.Empty; + public string Minister { get => _minister; set => SetProperty(ref _minister, value); } + private string _minister = string.Empty; + public string Where { get => _where; set => SetProperty(ref _where, value); } + private string _where = string.Empty; + public string Ref_No { get => _ref_No; set => SetProperty(ref _where, value); } +#pragma warning disable IDE0044 // Add readonly modifier + private string _ref_No = string.Empty; +#pragma warning restore IDE0044 // Add readonly modifier + public string Notes { get => _notes; set => SetProperty(ref _notes, value); } + private string _notes = string.Empty; + public string Filename { get => _filename; set => SetProperty(ref _filename, value); } + private string _filename = string.Empty; + public string Web { get => _web; set => SetProperty(ref _web, value); } + private string _web = string.Empty; + + public override bool Equals(object? obj) + { + return Equals(obj as MaintainSermonFilerModel); + } + + public bool Equals(MaintainSermonFilerModel? other) + { + return other is not null && + Seid == other.Seid && + Title == other.Title && + Scripture == other.Scripture && + When == other.When && + Subject == other.Subject && + Minister == other.Minister && + Where == other.Where && + Ref_No == other.Ref_No && + Notes == other.Notes && + Filename == other.Filename && + Web == other.Web; + } + + public override int GetHashCode() + { + HashCode hash = new(); + hash.Add(Seid); + hash.Add(Title); + hash.Add(Scripture); + hash.Add(When); + hash.Add(Subject); + hash.Add(Minister); + hash.Add(Where); + hash.Add(Ref_No); + hash.Add(Notes); + hash.Add(Filename); + hash.Add(Web); + return hash.ToHashCode(); + } + } +} diff --git a/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerPresenter.cs b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerPresenter.cs new file mode 100644 index 0000000..0c5190d --- /dev/null +++ b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerPresenter.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVPLearning.RecordKeeping.SermonFiler +{ + internal class MaintainSermonFilerPresenter + { + private readonly IMaintainSermonFilerView _view; + public MaintainSermonFilerPresenter(IMaintainSermonFilerView view) + { + _view = view; + + _view.AddButtonClicked += AddButtonClicked; + _view.DeleteButtonClicked += DeleteButtonClicked; + _view.LocateButtonClicked += LocateButtonClicked; + _view.NextButtonClicked += NextButtonClicked; + _view.PreviousButtonClicked += PreviousButtonClicked; + _view.CloseButtonClicked += CloseButtonClicked; + _view.LaunchButtonClicked += LaunchButtonClicked; + _view.BrowseButtonClicked += BrowseButtonClicked; + _view.LoadData(new() { Title = "Loaded model" }); + if (_view is Form form) { form.Show(); } + } + + private void NextButtonClicked(object? sender, int e) + { + MaintainSermonFilerModel model = new() + { + Title = "Next record ", + When = new DateTime(2024, 3, 1), + Filename = "nextfile" + }; + _view.LoadData(model); + } + private void BrowseButtonClicked(object? sender, EventArgs e) + { + } + + private void LaunchButtonClicked(object? sender, string e) + { + } + + private void CloseButtonClicked(object? sender, EventArgs e) + { + if (_view is Form form) { form.Close(); } + } + + private void PreviousButtonClicked(object? sender, int e) + { + } + + + + private void LocateButtonClicked(object? sender, int e) + { + } + + private void DeleteButtonClicked(object? sender, int e) + { + } + + internal void AddButtonClicked(object? sender, EventArgs e) + { + _view.LoadData(new() { Title = "I'm a new record", When = null }); + } + } +} diff --git a/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.Designer.cs b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.Designer.cs new file mode 100644 index 0000000..317d38d --- /dev/null +++ b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.Designer.cs @@ -0,0 +1,39 @@ +namespace MVPLearning.RecordKeeping.SermonFiler +{ + partial class MaintainSermonFilerView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Text = "MaintainSermonFilerView"; + } + + #endregion + } +} \ No newline at end of file diff --git a/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.cs b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.cs new file mode 100644 index 0000000..44db087 --- /dev/null +++ b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.cs @@ -0,0 +1,21 @@ +using MVPLearning.BaseLibrary; +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; + +namespace MVPLearning.RecordKeeping.SermonFiler +{ + public partial class MaintainSermonFilerView : BaseForm + { + public MaintainSermonFilerView() + { + InitializeComponent(); + } + } +} diff --git a/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.resx b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/MVPLearning/RecordKeeping/SermonFiler/MaintainSermonFilerView.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/MVPLearning/Structure/ObservableObject.cs b/MVPLearning/Structure/ObservableObject.cs new file mode 100644 index 0000000..ac6e01d --- /dev/null +++ b/MVPLearning/Structure/ObservableObject.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace MVPLearning.Structure +{ + internal class ObservableObject : INotifyPropertyChanged + { + public event PropertyChangedEventHandler? PropertyChanged; + protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = "") + { + if (EqualityComparer.Default.Equals(storage, value)) + { + return false; + } + storage = value; + RaisePropertyChanged(propertyName); + return true; + } + } +}