├── .gitignore ├── LICENSE ├── README.md ├── WinformsMvc.Example ├── App.config ├── Controllers │ ├── AccountController.cs │ ├── DefaultController.cs │ └── LoginController.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Views │ ├── AccountView.Designer.cs │ ├── AccountView.cs │ ├── AccountView.resx │ ├── DefaultView.Designer.cs │ ├── DefaultView.cs │ ├── DefaultView.resx │ ├── LoginView.Designer.cs │ ├── LoginView.cs │ └── LoginView.resx └── WinformsMvc.Example.csproj ├── WinformsMvc.sln └── WinformsMvc ├── AppManager.cs ├── Controller.cs ├── IView.cs ├── Properties └── AssemblyInfo.cs └── WinformsMvc.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Shane 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # winforms-mvc - A library for MVC pattern in c# Windows Forms Application 2 | MVC for C# Windows Forms 3 | 4 | ## MVC Usage 5 | 6 | To use the MVC framework, you'll have to make some changes to the class containing the `Main` method, defaults to `Program.cs` in WinForms applications. 7 | 8 | ``` 9 | static class Program 10 | { 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | 17 | AppManager.Start(); // replaced: Application.Run(formObject); where generic type TController is your starting controller 18 | } 19 | } 20 | ``` 21 | 22 | ##### AppManager 23 | 24 | The AppManager class is initially used to keep the STA (Single Threaded Apartment) thread running, because WinForms applications run on one single thread. The AppManager singleton can be used to "travel" to different forms using the `Load` method from this class. The Load method requires a generic type which inherits the abstract `Controller` class. When the entered generic type is `Loadable`, it will execute the successhandler of the controller. If the controller was not able to load, the application will prompt a message to the user and exits the application when the message closes using the failedhandler. Both success and failed handlers can be overridden. 25 | 26 | Because the AppManager is a singleton, we can use all the functionality of the AppManager instance anywhere in our application once the instance is initialized using `Start`. 27 | 28 | Example: 29 | ``` 30 | AppManager.Instance.Load(); 31 | ``` 32 | 33 | ##### Controllers 34 | 35 | Controllers are used to handle events or other functionalities that should be processed on the backend. I use this MVC framework for pushing and pulling of data on the controller. When the `view` submits the data entered in it's form, the data will be send to the controller through events (callbacks) and the controller will insert them in the prefered type of `repository`. 36 | 37 | Every controller must inherit the abstract Controller class or any other unsealed class that is derived from that class. 38 | 39 | Example: 40 | ``` 41 | public class LoginController : Controller 42 | { 43 | 44 | private LoginView _view; 45 | 46 | public override View 47 | { 48 | get 49 | { 50 | return _view; 51 | } 52 | } 53 | 54 | public LoginController() 55 | { 56 | _view = new LoginView(); 57 | _view.LoginAttempt += OnLoginAttemptHandler; 58 | } 59 | 60 | public override bool Loadable() 61 | { 62 | return AppManager.Instance.User == null; 63 | } 64 | 65 | protected void OnLoginAttemptHandler(LoginAttemptEventArgs e) { /* ... */ } 66 | 67 | } 68 | ``` 69 | 70 | ##### Views 71 | 72 | A `Form` is defined as a view in this MVC framework. This way we are not only benefitting from the built in designer of Visual Studios, but also the other libraries which alter or extend the designer of the winforms. A view does not know where the data is comming from, it has no relation to anything other than the `models`. 73 | 74 | When data, which was entered or created in the view, should be submitted to the backend, the view has to create an event which the controller can subscribe too to handle the submitted data (eg. store in dbo). 75 | 76 | Example: 77 | ``` 78 | public partial class LoginView : Form, IView 79 | { 80 | 81 | public event LoginAttemptEventHandler LoginAttempt; 82 | 83 | public LoginView() { /* ... */ } 84 | 85 | public Form Form 86 | { 87 | get 88 | { 89 | return this; 90 | } 91 | } 92 | 93 | public String Title 94 | { 95 | get 96 | { 97 | return Text; 98 | } 99 | set 100 | { 101 | Text = value; 102 | } 103 | } 104 | 105 | private void buttonLogin_Click(object sender, EventArgs e) 106 | { 107 | string email = null; // the entered email address 108 | string password = null; // the entered password 109 | 110 | bool flag = false; // checks if the entered fields are valid 111 | /* 112 | ... 113 | ... 114 | ... 115 | */ 116 | 117 | if (flag) 118 | { 119 | OnLoginAttempt(new LoginAttempt(email, password)); 120 | } 121 | } 122 | 123 | protected void OnLoginAttempt(LoginAttemptEventArgs e) 124 | { 125 | if (LoginAttempt != null) 126 | { 127 | LoginAttempt(e); 128 | } 129 | } 130 | 131 | } 132 | ``` 133 | -------------------------------------------------------------------------------- /WinformsMvc.Example/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WinformsMvc.Example.Views; 7 | 8 | namespace WinformsMvc.Example.Controllers 9 | { 10 | public class AccountController : Controller 11 | { 12 | private IView _view; 13 | public override IView View 14 | { 15 | get 16 | { 17 | return _view ?? new AccountView(); 18 | } 19 | } 20 | 21 | public override bool Loadable() 22 | { 23 | return false; // Could be used to check if an user was signed in. 24 | } 25 | 26 | protected override void OnLoadFailedHandler(object sender, EventArgs e) 27 | { 28 | base.OnLoadFailedHandler(sender, e); 29 | 30 | // Optionally run a custom controller failed handler. 31 | // On default it will prompt a message to the user with a message that application will close. 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Controllers/DefaultController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WinformsMvc.Example.Views; 7 | 8 | namespace WinformsMvc.Example.Controllers 9 | { 10 | public class DefaultController : Controller 11 | { 12 | private IView _view; 13 | public override IView View 14 | { 15 | get 16 | { 17 | return _view ?? new DefaultView(); 18 | } 19 | } 20 | 21 | public override bool Loadable() 22 | { 23 | return true; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Controllers/LoginController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WinformsMvc.Example.Views; 7 | 8 | namespace WinformsMvc.Example.Controllers 9 | { 10 | public class LoginController : Controller 11 | { 12 | private IView _view; 13 | public override IView View 14 | { 15 | get 16 | { 17 | return _view ?? new LoginView(); 18 | } 19 | } 20 | 21 | public override bool Loadable() 22 | { 23 | return true; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | using WinformsMvc.Example.Controllers; 7 | 8 | namespace WinformsMvc.Example 9 | { 10 | static class Program 11 | { 12 | /// 13 | /// The main entry point for the application. 14 | /// 15 | [STAThread] 16 | static void Main() 17 | { 18 | Application.EnableVisualStyles(); 19 | Application.SetCompatibleTextRenderingDefault(false); 20 | 21 | //Application.Run(new Form1()); 22 | AppManager.Start(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WinformsMvc.Example")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WinformsMvc.Example")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a404ce30-bdeb-43c7-9749-3ab514d1a012")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WinformsMvc.Example.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WinformsMvc.Example.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WinformsMvc.Example.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/AccountView.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace WinformsMvc.Example.Views 2 | { 3 | partial class AccountView 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.labelBack = new System.Windows.Forms.Label(); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.SuspendLayout(); 34 | // 35 | // labelBack 36 | // 37 | this.labelBack.AutoSize = true; 38 | this.labelBack.Location = new System.Drawing.Point(12, 9); 39 | this.labelBack.Name = "labelBack"; 40 | this.labelBack.Size = new System.Drawing.Size(46, 13); 41 | this.labelBack.TabIndex = 0; 42 | this.labelBack.Text = "<< back"; 43 | this.labelBack.Click += new System.EventHandler(this.labelBack_Click); 44 | // 45 | // label1 46 | // 47 | this.label1.AutoSize = true; 48 | this.label1.Location = new System.Drawing.Point(155, 122); 49 | this.label1.Name = "label1"; 50 | this.label1.Size = new System.Drawing.Size(63, 13); 51 | this.label1.TabIndex = 1; 52 | this.label1.Text = "User profile "; 53 | // 54 | // AccountView 55 | // 56 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 57 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 58 | this.ClientSize = new System.Drawing.Size(370, 261); 59 | this.Controls.Add(this.label1); 60 | this.Controls.Add(this.labelBack); 61 | this.Name = "AccountView"; 62 | this.Text = "AccountView"; 63 | this.ResumeLayout(false); 64 | this.PerformLayout(); 65 | 66 | } 67 | 68 | #endregion 69 | 70 | private System.Windows.Forms.Label labelBack; 71 | private System.Windows.Forms.Label label1; 72 | } 73 | } -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/AccountView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using WinformsMvc.Example.Controllers; 11 | 12 | namespace WinformsMvc.Example.Views 13 | { 14 | public partial class AccountView : Form, IView 15 | { 16 | public AccountView() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | public Form Form 22 | { 23 | get 24 | { 25 | return this; 26 | } 27 | } 28 | 29 | public string Title 30 | { 31 | get 32 | { 33 | return Text; 34 | } 35 | 36 | set 37 | { 38 | Text = value; 39 | } 40 | } 41 | 42 | private void labelBack_Click(object sender, EventArgs e) 43 | { 44 | AppManager.Instance.Load(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/AccountView.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/DefaultView.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace WinformsMvc.Example.Views 2 | { 3 | partial class DefaultView 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.button1 = new System.Windows.Forms.Button(); 33 | this.button2 = new System.Windows.Forms.Button(); 34 | this.button3 = new System.Windows.Forms.Button(); 35 | this.checkBox1 = new System.Windows.Forms.CheckBox(); 36 | this.label2 = new System.Windows.Forms.Label(); 37 | this.label3 = new System.Windows.Forms.Label(); 38 | this.SuspendLayout(); 39 | // 40 | // label1 41 | // 42 | this.label1.AutoSize = true; 43 | this.label1.Location = new System.Drawing.Point(20, 18); 44 | this.label1.Name = "label1"; 45 | this.label1.Size = new System.Drawing.Size(286, 13); 46 | this.label1.TabIndex = 0; 47 | this.label1.Text = "Winforms designer and extensions for designer will still work"; 48 | // 49 | // button1 50 | // 51 | this.button1.Location = new System.Drawing.Point(73, 89); 52 | this.button1.Name = "button1"; 53 | this.button1.Size = new System.Drawing.Size(64, 30); 54 | this.button1.TabIndex = 1; 55 | this.button1.Text = "button1"; 56 | this.button1.UseVisualStyleBackColor = true; 57 | this.button1.Click += new System.EventHandler(this.button1_Click); 58 | // 59 | // button2 60 | // 61 | this.button2.Location = new System.Drawing.Point(103, 158); 62 | this.button2.Name = "button2"; 63 | this.button2.Size = new System.Drawing.Size(111, 22); 64 | this.button2.TabIndex = 2; 65 | this.button2.Text = "button2"; 66 | this.button2.UseVisualStyleBackColor = true; 67 | // 68 | // button3 69 | // 70 | this.button3.Location = new System.Drawing.Point(182, 93); 71 | this.button3.Name = "button3"; 72 | this.button3.Size = new System.Drawing.Size(52, 22); 73 | this.button3.TabIndex = 3; 74 | this.button3.Text = "button3"; 75 | this.button3.UseVisualStyleBackColor = true; 76 | this.button3.Click += new System.EventHandler(this.button3_Click); 77 | // 78 | // checkBox1 79 | // 80 | this.checkBox1.AutoSize = true; 81 | this.checkBox1.Location = new System.Drawing.Point(152, 132); 82 | this.checkBox1.Name = "checkBox1"; 83 | this.checkBox1.Size = new System.Drawing.Size(15, 14); 84 | this.checkBox1.TabIndex = 4; 85 | this.checkBox1.UseVisualStyleBackColor = true; 86 | // 87 | // label2 88 | // 89 | this.label2.AutoSize = true; 90 | this.label2.Location = new System.Drawing.Point(61, 73); 91 | this.label2.Name = "label2"; 92 | this.label2.Size = new System.Drawing.Size(91, 13); 93 | this.label2.TabIndex = 5; 94 | this.label2.Text = "~~~~~~~~~~~~"; 95 | // 96 | // label3 97 | // 98 | this.label3.AutoSize = true; 99 | this.label3.Location = new System.Drawing.Point(174, 73); 100 | this.label3.Name = "label3"; 101 | this.label3.Size = new System.Drawing.Size(70, 13); 102 | this.label3.TabIndex = 6; 103 | this.label3.Text = "~~~~~~~~~"; 104 | // 105 | // DefaultView 106 | // 107 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 108 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 109 | this.ClientSize = new System.Drawing.Size(328, 261); 110 | this.Controls.Add(this.label3); 111 | this.Controls.Add(this.label2); 112 | this.Controls.Add(this.checkBox1); 113 | this.Controls.Add(this.button3); 114 | this.Controls.Add(this.button2); 115 | this.Controls.Add(this.button1); 116 | this.Controls.Add(this.label1); 117 | this.Name = "DefaultView"; 118 | this.Text = "DefaultView"; 119 | this.ResumeLayout(false); 120 | this.PerformLayout(); 121 | 122 | } 123 | 124 | #endregion 125 | 126 | private System.Windows.Forms.Label label1; 127 | private System.Windows.Forms.Button button1; 128 | private System.Windows.Forms.Button button2; 129 | private System.Windows.Forms.Button button3; 130 | private System.Windows.Forms.CheckBox checkBox1; 131 | private System.Windows.Forms.Label label2; 132 | private System.Windows.Forms.Label label3; 133 | } 134 | } -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/DefaultView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using WinformsMvc.Example.Controllers; 11 | 12 | namespace WinformsMvc.Example.Views 13 | { 14 | public partial class DefaultView : Form, IView 15 | { 16 | public DefaultView() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | public Form Form 22 | { 23 | get 24 | { 25 | return this; 26 | } 27 | } 28 | 29 | public string Title 30 | { 31 | get 32 | { 33 | return Text; 34 | } 35 | set 36 | { 37 | Text = value; 38 | } 39 | } 40 | 41 | private void button1_Click(object sender, EventArgs e) 42 | { 43 | AppManager.Instance.Load(); 44 | } 45 | 46 | private void button3_Click(object sender, EventArgs e) 47 | { 48 | AppManager.Instance.Load(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/DefaultView.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/LoginView.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace WinformsMvc.Example.Views 2 | { 3 | partial class LoginView 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.labelBack = new System.Windows.Forms.Label(); 32 | this.textBox1 = new System.Windows.Forms.TextBox(); 33 | this.textBox2 = new System.Windows.Forms.TextBox(); 34 | this.button1 = new System.Windows.Forms.Button(); 35 | this.label1 = new System.Windows.Forms.Label(); 36 | this.label2 = new System.Windows.Forms.Label(); 37 | this.SuspendLayout(); 38 | // 39 | // labelBack 40 | // 41 | this.labelBack.AutoSize = true; 42 | this.labelBack.Location = new System.Drawing.Point(12, 9); 43 | this.labelBack.Name = "labelBack"; 44 | this.labelBack.Size = new System.Drawing.Size(46, 13); 45 | this.labelBack.TabIndex = 0; 46 | this.labelBack.Text = "<< back"; 47 | this.labelBack.Click += new System.EventHandler(this.labelBack_Click); 48 | // 49 | // textBox1 50 | // 51 | this.textBox1.Location = new System.Drawing.Point(27, 84); 52 | this.textBox1.Name = "textBox1"; 53 | this.textBox1.Size = new System.Drawing.Size(95, 20); 54 | this.textBox1.TabIndex = 1; 55 | // 56 | // textBox2 57 | // 58 | this.textBox2.Location = new System.Drawing.Point(27, 133); 59 | this.textBox2.Name = "textBox2"; 60 | this.textBox2.Size = new System.Drawing.Size(95, 20); 61 | this.textBox2.TabIndex = 2; 62 | // 63 | // button1 64 | // 65 | this.button1.Location = new System.Drawing.Point(47, 178); 66 | this.button1.Name = "button1"; 67 | this.button1.Size = new System.Drawing.Size(75, 23); 68 | this.button1.TabIndex = 3; 69 | this.button1.Text = "signin"; 70 | this.button1.UseVisualStyleBackColor = true; 71 | // 72 | // label1 73 | // 74 | this.label1.AutoSize = true; 75 | this.label1.Location = new System.Drawing.Point(24, 68); 76 | this.label1.Name = "label1"; 77 | this.label1.Size = new System.Drawing.Size(55, 13); 78 | this.label1.TabIndex = 4; 79 | this.label1.Text = "Username"; 80 | // 81 | // label2 82 | // 83 | this.label2.AutoSize = true; 84 | this.label2.Location = new System.Drawing.Point(24, 117); 85 | this.label2.Name = "label2"; 86 | this.label2.Size = new System.Drawing.Size(53, 13); 87 | this.label2.TabIndex = 5; 88 | this.label2.Text = "Password"; 89 | // 90 | // LoginView 91 | // 92 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 93 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 94 | this.ClientSize = new System.Drawing.Size(144, 261); 95 | this.Controls.Add(this.label2); 96 | this.Controls.Add(this.label1); 97 | this.Controls.Add(this.button1); 98 | this.Controls.Add(this.textBox2); 99 | this.Controls.Add(this.textBox1); 100 | this.Controls.Add(this.labelBack); 101 | this.Name = "LoginView"; 102 | this.Text = "LoginController"; 103 | this.ResumeLayout(false); 104 | this.PerformLayout(); 105 | 106 | } 107 | 108 | #endregion 109 | 110 | private System.Windows.Forms.Label labelBack; 111 | private System.Windows.Forms.TextBox textBox1; 112 | private System.Windows.Forms.TextBox textBox2; 113 | private System.Windows.Forms.Button button1; 114 | private System.Windows.Forms.Label label1; 115 | private System.Windows.Forms.Label label2; 116 | } 117 | } -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/LoginView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using WinformsMvc.Example.Controllers; 11 | 12 | namespace WinformsMvc.Example.Views 13 | { 14 | public partial class LoginView : Form, IView 15 | { 16 | public LoginView() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | public Form Form 22 | { 23 | get 24 | { 25 | return this; 26 | } 27 | } 28 | 29 | public string Title 30 | { 31 | get 32 | { 33 | return Text; 34 | } 35 | 36 | set 37 | { 38 | Text = value; 39 | } 40 | } 41 | 42 | private void labelBack_Click(object sender, EventArgs e) 43 | { 44 | AppManager.Instance.Load(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /WinformsMvc.Example/Views/LoginView.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /WinformsMvc.Example/WinformsMvc.Example.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A404CE30-BDEB-43C7-9749-3AB514D1A012} 8 | WinExe 9 | Properties 10 | WinformsMvc.Example 11 | WinformsMvc.Example 12 | v4.6 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Form 54 | 55 | 56 | LoginView.cs 57 | 58 | 59 | 60 | 61 | Form 62 | 63 | 64 | AccountView.cs 65 | 66 | 67 | Form 68 | 69 | 70 | DefaultView.cs 71 | 72 | 73 | LoginView.cs 74 | 75 | 76 | ResXFileCodeGenerator 77 | Resources.Designer.cs 78 | Designer 79 | 80 | 81 | True 82 | Resources.resx 83 | 84 | 85 | AccountView.cs 86 | 87 | 88 | DefaultView.cs 89 | 90 | 91 | SettingsSingleFileGenerator 92 | Settings.Designer.cs 93 | 94 | 95 | True 96 | Settings.settings 97 | True 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | {2a6ae87c-38c2-4e19-bd67-b5b31085cd11} 106 | WinformsMvc 107 | 108 | 109 | 110 | 117 | -------------------------------------------------------------------------------- /WinformsMvc.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinformsMvc", "WinformsMvc\WinformsMvc.csproj", "{2A6AE87C-38C2-4E19-BD67-B5B31085CD11}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinformsMvc.Example", "WinformsMvc.Example\WinformsMvc.Example.csproj", "{A404CE30-BDEB-43C7-9749-3AB514D1A012}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2A6AE87C-38C2-4E19-BD67-B5B31085CD11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {2A6AE87C-38C2-4E19-BD67-B5B31085CD11}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {2A6AE87C-38C2-4E19-BD67-B5B31085CD11}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {2A6AE87C-38C2-4E19-BD67-B5B31085CD11}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {A404CE30-BDEB-43C7-9749-3AB514D1A012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {A404CE30-BDEB-43C7-9749-3AB514D1A012}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {A404CE30-BDEB-43C7-9749-3AB514D1A012}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {A404CE30-BDEB-43C7-9749-3AB514D1A012}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /WinformsMvc/AppManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace WinformsMvc 10 | { 11 | public class AppManager 12 | { 13 | private static bool _started; 14 | 15 | private static AppManager _instance; 16 | 17 | public static AppManager Instance 18 | { 19 | get 20 | { 21 | if (!_started) 22 | throw new Exception("Tried to call the singleton instance of the AppManager before the AppManager started."); 23 | 24 | return _instance; 25 | } 26 | } 27 | 28 | /// 29 | /// The current WinForms-Form instance 30 | /// 31 | private IView _currentView; 32 | 33 | /// 34 | /// Private constructor to prevent instantiation 35 | /// 36 | private AppManager() { } 37 | 38 | /// 39 | /// Starts the AppManager and creates a singleton for this class 40 | /// 41 | public static void Start() 42 | where T : Controller 43 | { 44 | if (_started) return; 45 | 46 | _started = true; 47 | 48 | T controller = Activator.CreateInstance(); 49 | 50 | if (controller != null) 51 | { 52 | _instance = new AppManager() 53 | { 54 | _currentView = controller.View 55 | }; 56 | 57 | _instance.openForm(); 58 | } 59 | else 60 | { 61 | Application.Exit(); 62 | } 63 | } 64 | 65 | /// 66 | /// Loads a Controller, handles the loading state 67 | /// 68 | /// Generic Type where T extends Controller 69 | public void Load() 70 | where T : Controller 71 | { 72 | T controller = Activator.CreateInstance(); 73 | 74 | if (controller != null) 75 | { 76 | if (controller.Loadable()) 77 | { 78 | controller.OnLoadSuccess(EventArgs.Empty); 79 | } 80 | else 81 | { 82 | controller.OnLoadFailure(EventArgs.Empty); 83 | } 84 | } 85 | else 86 | { 87 | Application.Exit(); 88 | } 89 | } 90 | 91 | /// 92 | /// Shows the View of the Controller parameter 93 | /// 94 | /// The controller instance 95 | public void Show(Controller controller) 96 | { 97 | if (_currentView != null) 98 | { 99 | _currentView.Close(); 100 | _currentView.Form.Dispose(); 101 | } 102 | 103 | _currentView = controller.View; 104 | 105 | Thread th = new Thread(openForm); 106 | th.SetApartmentState(ApartmentState.STA); 107 | th.Start(); 108 | } 109 | 110 | /// 111 | /// Used as single-threaded appartment thread-callback to keep the main thread running 112 | /// 113 | private void openForm() 114 | { 115 | Application.Run(_currentView.Form); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /WinformsMvc/Controller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace WinformsMvc 9 | { 10 | public abstract class Controller 11 | { 12 | 13 | public abstract IView View { get; } 14 | 15 | public event EventHandler LoadSuccess, LoadFailed; 16 | 17 | public Controller() 18 | { 19 | LoadSuccess += OnLoadSucceededHandler; 20 | LoadFailed += OnLoadFailedHandler; 21 | } 22 | 23 | public abstract bool Loadable(); 24 | 25 | protected virtual void OnLoadSucceededHandler(Object sender, EventArgs e) 26 | { 27 | AppManager.Instance.Show(this); 28 | } 29 | 30 | protected virtual void OnLoadFailedHandler(Object sender, EventArgs e) 31 | { 32 | if (MessageBox.Show("You don't have access to load this page.\nThe application will exit now.") == DialogResult.OK) 33 | { 34 | Application.Exit(); 35 | } 36 | } 37 | 38 | public void OnLoadSuccess(EventArgs e) 39 | { 40 | if (LoadSuccess != null) 41 | LoadSuccess(this, e); 42 | } 43 | 44 | public void OnLoadFailure(EventArgs e) 45 | { 46 | if (LoadFailed != null) 47 | LoadFailed(this, e); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /WinformsMvc/IView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace WinformsMvc 9 | { 10 | public interface IView 11 | { 12 | string Title { get; set; } 13 | 14 | Form Form { get; } 15 | 16 | void Close(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WinformsMvc/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WinformsMvc")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WinformsMvc")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2a6ae87c-38c2-4e19-bd67-b5b31085cd11")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WinformsMvc/WinformsMvc.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2A6AE87C-38C2-4E19-BD67-B5B31085CD11} 8 | Library 9 | Properties 10 | WinformsMvc 11 | WinformsMvc 12 | v4.6 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | --------------------------------------------------------------------------------