Winforms Application Template - winforms

I am trying to create a Winforms application with a generic template i.e. all the forms will inherit a predefined template for new, save, edit, delete buttons and some generic images and rest of the stuff I will put manually of inheriting forms.
Any suggestions how to achieve this would be greatly appreciated.

I would create a new form as the template-like one and force it to implement an interface, in my sample below I named that interface IApplicationWindow, with the declaration of the common methods that are intended to be implemented by the sub-classes.
I would also place in the template-like form, in addition to the common controls you mention, all the stuff that should be commonly used along all windows like logging helper classes and so on.
Assuming that we've defined already an interface named IApplicationWindow, a template-like form would look like this:
public partial class TemplateForm : Form, IApplicationWindow
{
// Place here as protected class members all object instances
// that are common to all your forms, like helper class for logging
// purposes or security delegates.
[...]
public TemplateForm()
{
InitializeComponent();
}
#region IApplicationWindow interface implementation
public virtual void Save()
{
// Do nothing unless you need common behavior.
// Leave extenders implement the concrete behavior.
}
public virtual void Edit()
{
// Do nothing unless you need common behavior.
// Leave extenders implement the concrete behavior.
}
[...]
#endregion
}
And this is how a form extending the your template-like form would looks like (note that you must override the methods to provide an specific implementation):
public partial class AnApplicationWindow : TemplateForm
{
public AnApplicationWindow()
{
InitializeComponent();
}
public override void Save()
{
base.Save();
// Implement specific behavior here
}
public override void Edit()
{
base.Edit();
// Implement specific behavior here
}
[...]
}
Finally I would place carefully the common controls in the UI of the template form so that if you resize the extending forms the controls are placed correclty (use correctly the anchors).

Related

How to use MainWindow as ShellViewModel View?

I understand that by default CM will look for ShellView in Views folder to use as ShellViewModel View but I want to use the MainWindow instead... can this be done and how?
How it Works
CM uses a set of View/ViewModel Naming Conventions, generally speaking, if you have a ViewModel named FooViewModel CM will attempt to locate a type with a similar name of FooView or FooPage.
What if you really want "MainWindow" and "ShellViewModel"?
If you just wanted to use an existing "MainWindow" with an existing 'root viewmodel' then consider subclassing Bootstrapper<TRootModel> and override OnStartUp. This is a prescribed method, but can seem daunting.
(I have not tested this code.)
protected override void OnStartup(object sender, StartupEventArgs e)
{
var rootModel = IoC.Get<TRootModel>();
var rootView = new MainWindow();
ViewModelBinder.Bind(rootModel, rootView, this);
rootView.Show();
}
The above method, of course, would only apply to the initial view for the root view model shown during start-up. Future attempts to display a view for ShellViewModel may work, or they may result in errors, I am not certain.
Extending Conventions
There are a few ways to customize the convention itself. The most flexible and direct method is to intercept/hook Caliburn.Micro.ViewLocator.LocateForModelType, this allows you to modify the behavior/strategy applied during view location.
private static void CustomViewLocatorStrategy()
{
// store original implementation so we can fall back to it as necessary
var originalLocatorStrategy = Caliburn.Micro.ViewLocator.LocateForModelType;
// intercept ViewLocator.LocateForModelType requests and apply custom mappings
Caliburn.Micro.ViewLocator.LocateForModelType = (modelType, displayLocation, context) =>
{
// implement your custom logic
if (modelType == typeof(ShellViewModel))
{
return new MainWindow();
}
// fall back on original locator
return originalLocatorStrategy(modelType, displayLocation, context);
};
}
The above can be called from inside a Bootstrapper<TRootModel>.Configure override:
protected override void Configure()
{
CustomViewLocatorStrategy();
base.Configure();
}
This method is more likely to play well with CM (in terms of any view caching, namely.) However, it still breaks conventions, and it's still a fair amount of code.
Registering Additional Suffixes?
One thing I want to point out, but have not had a chance to play with, is ViewLocator.RegisterViewSuffix implementation. I believe if you executed ViewLocator.RegisterViewSuffix(#"Window") then you could rely on CM to map MainViewModel to MainWindow.
This would allow for more expressive suffixes (such as Window, Dialog, Form, or others you may want to use.) Personally I dislike the use of 'View' as a suffix, I believe it's too generic (after all, they are all Views.)
Caliburn.Micro doesn't look for ShellView by default, this is how things work. Let's say you have a bootstrapper defined like this:
class MyBootsrtapper : Bootstrapper<MyViewModel> { }
Then CM (Caliburn.Micro) will look for a view named MyView. So yes you can use MainWindow instead as long as your view model name is MainWindowViewModel.
I have answered the other question you have asked and it seems you don't fully comprehend CM so i really really advise you to Start Here and you can always check the projects Documentation on codeplex because it contains all updated information and documentation.
Edit:
Caliburn.Micro uses a simple naming convention to locate Views for
ViewModels. Essentially, it takes the FullName and removes “Model”
from it. So, given MyApp.ViewModels.MyViewModel, it would look for
MyApp.Views.MyView.
Taken from official documentation here.

Communication between winforms in mvp pattern

I'm dealing with a big problem for developing my app. It's a Winforms base application on C# implementing the Model-View-Presenter pattern, but I am new to this method. I've searched everywhere and haven't found an answer to my issue.
I need to know how I can use this pattern to allow communication between winforms, and how the presenter must show them without coupling the presenter to the form. I've seen a way using Factory pattern, but don't understand how to implement it.
Any help or point in the right direction would be appreciated.
Assertion
The Presenter is responsible for coordination between the View and Model (if following the Passive View implementation).
This could look like:
A View instantiating the Presenter and injecting itself into the Presenter:
IPresenter presenter;
public View() { presenter = new Presenter(this) }
A Presenter instantiating one or more views and injecting itself into the view(s):
IView1 view1;
public Presenter() { view1 = new View1(this) }
IView1 view1;
IView2 view2;
public Presenter() { view1 = new View1(this); view2 = new View2(this); }
Example
In your case, a Presenter coordinating multiple views might look something like this (pseudo):
public class Presenter : IPresenter
{
IView1 view1;
IView2 view2;
public Presenter()
{
view1 = new View1(this);
view2 = new View2(this);
}
private WireViewEvents()
{
view1.OnButtonClick += HandleButtonClickFromView1;
}
public void HandleButtonClickFromView1()
{
view2.SetSomeData();
view2.Show();
}
In this example, an event raised by View1 is handled by the Presenter, data is set in View2, and View2 is shown.
Keep in mind that no matter what your implementation is, the goals of MVP are:
Separation of concerns (UI seperate from domain logic).
Increasing testability.
Keep that this is just a basic example of how a Presenter might coordinate multiple views. If you want to abstract your View creation from the presenter you might move the creation into another container that the Presenter calls in to to create Views and subscribe to their events.
In MVP ,winforms should not communicate with each other.
Form A knows its Presenter A,
Form B knows its presenter B
Usually , you will modify model with form A through Prensenter A. Presenter B will listen to model changes,and will refresh Form B accordingly
If you need more coordination, you may consider using an Application Controller
See http://dotnetslackers.com/articles/designpatterns/The-Presenter-in-MVP-Implementations.aspx
I am just showing a dummy code in which 2 views are trying to communicate to each other through Presenter using interfaces. It is a simple example and let mw know if something is breaking. I have not tested this code to be honest.
namespace WindowsFormsApplication1
{
internal class View1 : IView1
{
public View1()
{
new Presenter(this);
}
public string Username { get; set; }
public event EventHandler ShowDetails;
}
}
namespace WindowsFormsApplication1
{
internal class View2 : IView2
{
public View2()
{
new Presenter(this);
}
public string Position { get; set; }
}
}
namespace WindowsFormsApplication1
{
public class Presenter
{
private readonly IView1 _view1;
private readonly IView2 _view2;
public Presenter(IView1 view1)
{
_view1 = view1;
_view1.ShowDetails += ShowDetails;
}
private void ShowDetails(object sender, EventArgs e)
{
_view2.Position = _view1.Username == "My Name" ? "Arhchitect" : "Project Manager";
}
public Presenter(IView2 view2)
{
_view2 = view2;
}
}
}
public interface IView1
{
string Username { get; set; }
event EventHandler ShowDetails;
}
public interface IView2
{
string Position { get; set; }
}
But after this example some notes. To start with your application try to decide first weather you want to go with 1 View interface or 2. There may be chances and even ease if you can use a single interface.
I think the points made earlier about the model raising events to make a presenter aware of changes is correct. I do have a couple comments I hope will be useful.
First, the View implementation might not be a single form. Sometimes, it makes sense for part of the model to be maintained by a separate (probably modal) form that really acts like a complex control in the View. In that case, the interaction between the forms would be direct. The Presenter should not care how the View implementation is done.
Second, when it looks like forms need to interact that are not clearly part of the same view (a lookup form, for example) I would recommand using the Application Controller pattern. In this case, when Form A needs to perform a function (like, "Find Product" or "Edit Details") it will call a method on it's own Presenter to do that. The Presenter then calls a separate method on the Application Controller (which all Presenters reference, it's a singleton) and the Application Controller opens the requried form which has its own Presenter. In WinForms, this could all be done with a modal form, in which case the results are sent back through the call chain. Alternatively, some event raising between the Application Controller and Presenters would be needed - i.e. the Presenter raises events on the Application Controller about what it has done and other Presenters substribing to that event are thus notified.
More on the Application Controller pattern in MVP can be found on my blog post Using the MVP Pattern

Using WPF design data with the MVVM pattern

I'm using the MVVM pattern in our WPF application to allow for comprehensive unit testing. The MVVM pattern itself is working great, however I'm struggling to adapt the pattern in a way that means I can use the design-time data support of WPF.
As I'm using Prism the ViewModel instances are generally injected into the constructor of the view, like so
public MyView(MyViewModel viewModel)
{
DataContext = viewModel;
}
Dependencies for the ViewModel are then injected into the constructor, like so
public class MyViewModel
{
public MyViewModel(IFoo foo, IBar bar)
{
// ...
}
// Gets and sets the model represented in the view
public MyModel { get; set; }
// Read-only properties that the view data binds to
public ICollectionView Rows { get; }
public string Title { get; }
// Read-write properties are databound to the UI and are used to control logic
public string Filter { get; set; }
}
This is generally working really well except when it comes to design data - I wanted to avoid compiling design-data specific classes into my released assembly and so I opted to use the {d:DesignData} approach instead of the {d:DesignInstance} approach, however in order for this to work correctly my ViewModel now needs to have a parameterless constructor. In addition, I also often need to change additional properties either to have setters or to be modifiable collections in order to be able to set these properties in XAML.
public class MyViewModel
{
public MyViewModel()
{
}
public MyViewModel(IFoo foo, IBar bar)
{
// ...
}
// Gets and sets the model represented in the view
public MyModel { get; set; }
// My read-only properties are no longer read-only
public ObservableCollection<Something> Rows { get; }
public string Title { get; set; }
public string Filter { get; set; }
}
This is worrying me:
I have a parameterless constructor that is never intended to be called and isn't unit tested
There are setters for properties that only the ViewModel itself should be calling
My ViewModel is now a jumbled mixture of properties that should be modified by the view, and those that shouldn't - this makes it tricky to tell at a glance which piece of code is responsible for maintaining any given property
Setting certain properties at design time (e.g. to see styling on the Filter text) can actually end up invoking ViewModel logic! (so my ViewModel also needs to be tollerant of otherwise mandatory dependencies being missing at design time)
Is there a better way to get design-time data in a WPF MVVM application in a way that doesn't compromise my ViewModel in this way?
Alternatively should I be building my ViewModel differently so that it has more simple properties with the logic separated out somewhere else.
First, I would recommend you to have a look at this video where Brian Lagunas provides several best practices about MVVM. Brian is - at least - involved in the development of Prism, as his name appears in the nuget packages information. Didn't check further.
On my side I only use bits of Prism, and my Model and ViewModel always offer blank constructors (like what Brian shows), the data context is assigned in the view's XAML, and I set the properties values like :
<MyView.DataContext>
<MyViewModel />
</MyView.DataContext>
and
public void BringSomethingNew()
{
var myView = new View();
(myView.DataContext as ViewModel).Model = myModel;
UseMyView();
}
Another benefit with this approach is that the ViewModel is created once, with the same path at design and run time, so you create less objects and save GC efforts. I find this elegant.
With regards to the setters, the design data will still work if you make them private, like:
public string MyProp { get; private set; }
Ok, customize it to manage NotifyPropertyChange at your convenience, but you've got the idea.
Now, I don't have yet a solution to manage ObesrvableCollections (I face the same problem, although putting multiple values in XAML sometimes work... ???), and yes, I agree that you have to manage the case when the properties are not set, like setting default values in the constructor.
I hope this helps.
I too have worked with NUnit testing with WPF and MVVM implementation. However, my version is reversed from yours. You are creating the view first, then creating the model to control it.
In my version, I create the MVVM model FIRST and can unit test it till the cows come home and not worry about any visual design... if the model is broken, so too will the visual implementation.
in my MVVM model, I have a method to "GetTheViewWindow". So, when I derive from my MVVM baseline, each view model has its own view its responsible for. So via a virtual method, each instance will do its own new view window when being applied for production.
public class MyMVVMBase
{
private MyViewBaseline currentView;
public MyMVVMBase()
{ // no parameters required }
public virtual void GetTheViewWindow()
{ throw new exception( "You need to define the window to get"; ) }
}
public class MyXYZInstanceModel : MyMVVMBase
{
public override void GetTheViewWindow()
{
currentView = new YourActualViewWindow();
}
}
Hope this helps as an alternative to what you are running into.

Custom property injection in Castle Windsor for Windows Forms

I have a Windows Forms application which makes use of an MVP pattern. Each view is a WinForms user control and is backed by a presenter which handles non-UI concerns. The application makes use of Castle Windsor, and all views presenters and many other components are resolved via the Windsor Container.
What I would like to be able to do is customise property injection for the user control views. My views don't make a whole lot of use of property injection, but it is occasionally very useful and works well. The problem is, my user controls often contain nested controls, which in turn can contain other nested controls, and property injection is not going to work for these nested controls, because they were not directly resolved via the container.
What I would like to do is to configure property injection for components that inherit from the SWF Control class. In addition to finding properties on the component, I would like to also find properties on nested controls (in the Controls) collection and inject into these nested properties as well.
I know that Castle Windsor is extremely flexible and configurable so this may be possible. I need a bit of a nudge in the right direction though. Is this possible? Has anyone tried to do something similar?
If I have understood your question correctly I think that the only way to achieve what you want is by some sort of poor man's dependency injection because the way the winforms designer generates a method that constructs the various sub-controls you speak of makes it decidedly uncondusive to IoC.
I am not sure you will be able to do property injection but you can utilise the constructor, here is a hair-brained scheme I have just concocted ...
Firstly, create some way to access your windsor container - something like this would probably do the trick:
public static class MyContainer
{
private static readonly IWindsorContainer _container = Bootstrap();
// I did it like this so that there is no explicit dependency
// on Windsor - this would be the only place you need to change
// if you want an alternate container (how much you care about
// that is up to you)
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
private static IWindsorContainer Bootstrap()
{
var container = new WindsorContainer();
container.Install(FromAssembly.This());
// ... whatever else you need to do here
return container;
}
}
Secondly, in the inner controls, where you want some properties injected do something like this (I went for the good ol' ILogger as an example of something you may want injected):
public partial class MyFancyControl : UserControl
{
// Constructor to keep the winforms designer happy
public MyFancyControl()
: this (MyContainer.Resolve<ILogger>())
{
// Intentionally always blank as this
// is an un-unit-testable method
}
// Constructor that does the actual work
public MyFancyControl(ILogger logger)
{
InitializeComponent();
Logger = logger;
}
public ILogger Logger { get; private set; }
}
Note: using the logger raises one of the couple of obvious smells in this - sometimes you don't register such a component with the container at all (usually you have a null logger) so you may need to hook up some sort of mechanism for that but I leave that up to you if you need it or not.

load event not fired in inherited user control loaded from another assembly (Winforms)

I have an application with plugin-like structure.
all application forms inherit from a base UserControl :
public class BaseUserControl : UserControl
{
// some common properties and methods
//
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
}
and are compiled in different assemblies.
When I want to show a form, it goes through this sequence:
assembly = Assembly.LoadFile(assemblypath);
.
.
frm = (BaseUserControl)assembly.CreateInstance(frmname);
.
.
SomeContainer.Controls.Add(frm);
MainScreen.Controls.Add(SomeContainer);
Common structure of these forms is :
public class TestForm : BaseUserControl {
public TestForm(){InitializeComponent();}
private void InitializeComponent(){
.
.
this.Load += new System.EventHandler(this.TestForm_Load);
.
}
private void TestForm_Load(object sender, EventArgs e){}
}
The problem is that the Load event of these forms does not get fired.
Another behavior, I don't understand how, when setting a break point at the OnLoad in the base class, the call stack shows that is called from within the InitializeComponent.
Any ideas on how to solve this?
You are hopelessly mixing up the terms Form and UserControl, making it very hard to give a good answer. They are very different beasts, you can't turn a UC into a form. It is a client window, not a top-level window. I suspect that has something to do with your problem but the generic diagnostic is that somebody is overriding OnLoad and not calling base.OnLoad().
Yes, OnLoad may be called from code in InitializeComponent(). It isn't very healthy since OnLoad will run before the constructor is finished, but it is supported. This will happen when you touch a property that requires the Handle to be created. The call stack should show you which particular property assignment did this, just double-click the line in the call stack.

Resources