OOP vs case statement in Windows forms application - winforms

I have a software design question. Say I have a Windows form with some elements and I have a customer object. A customer can either be business, private or corporate for example.
Now, all the decisions of what is going to happen in the form will depend on the customer type. For instance, certain elements will be hidden, certain label text will be different, etc...events will respond differently.
Obviously, one way to code this will be to use CASE statement each time the decision needs to be made. Another way would be to have a Customer class and 3 other classed such as BusinessCustomer, PrivateCustomer and CorporateCustomer inherit from the base class. In the latter, a question then arises: how are you going to incorporate a windows from into it....
Edited
I had an idea: can I embed forms within forms? My reqs don't dictate two windows being shown at once, so I don't have to use MDI. But to simplify my design based on some ppl's comments here, I would like to maintain 3 different customer forms, and embed inside the main form on the fly. That way three GUIs are separated and I won't have to deal with every control's visibility.
I am assuming I can just add a form to another form, such as this:
Form child_form = new Form();
parent_form.Controls.Add(child_form);

Those decisions really shouldn't be made in the GUI. You should have a ViewModel behind your GUI that makes those decisions, and that you write unit tests for. (Or a Presenter, or a Controller -- different names that all mean roughly the same thing: get the decisions out of the GUI class and into something you can unit test.)
Then your ViewModel would have e.g. a Boolean property for each element that the GUI would disable, and a method for each action you could take (CloseCustomerAccount() or whatever).
As long as the Form is created for a particular type of customer, and the customer won't change to a different type of customer during the lifetime of the form, you could just pass your Customer object (that stores all of the actual customer data) to the ViewModel's constructor, and then pass your ViewModel to your Form's constructor. The form could set all its Enabled properties right after it calls InitializeComponent(). On the other hand, if the customer type could change, then your ViewModel needs to expose some events for the Form to hook, so the form knows when to re-run its Enabling logic.
Your question then moves out of the Form and into the ViewModel. Do you have one ViewModel class with a bunch of case statements, or three ViewModel classes (maybe with a fourth that's a base class) that use polymorphism, and a factory method somewhere that decides, based on the particular customer, which ViewModel class to instantiate?
I'd let your code be the guide there. Start with the simplest approach, which is probably case statements. Write a unit test for every behavior you care about. If the case statements start to get too awkward, then add a ViewModel descendant for each customer type, and start extracting the case statements into virtual methods. Your tests will catch you if you make a mistake during the refactor.

If you do have 3 different windows, each handling a specific type of customer than there won't be much point in working with the base class or a contract. You could be smart though with a factory class that takes a customer class and determines the correct screen to use.
I've run into this quite a bit. I end up with a base window that handles the generic stuff and then extend it for each concrete type.

I agree with Joshua Belden's answer. Three separate forms for different kinds of customers would likely be the easiest to maintain.
Also, in case you didn't know already, you can derive from a Form class and tweak it in a derived Form class. This is even supported by the designer.
However, I'd like to offer an alternative:
The Bridge Pattern: separate an abstraction from its implementation so the two can vary independently.
What you could do is this:
Create three separate UIImplementation classes. These classes could tweak the UI, and the events for the Customer form. In order to gain access to the private members of the form, you would need to declare the UIImplementation classes as nested within the CustomerForm class. (Use partial classes to separate these into different files). If the form itself is significant, and the tweaks are insignificant, this may be good option. It's difficult to say.

Just go for the three classes implementing some abstract Customer interface. In your app you would have a variable customer of type Customer and an object of a particular Customer type would be stored in there. Your GUI could then just rely on the interface and invoke methods on the customer variable regardless of what customer would be actually interacting with the GUI.
Have a look at this article.

I would go with an MVP type approach and define CustomerPresenter class that exposes a boolean property that will derive your UI controls' enable/disable state via binding.
public class CustomerPresenter
{
private Customer _customer;
public CustomerPresenter(Customer customer)
{
_customer = customer;
}
public bool EnableUI
{
get
{
//TODO: put your customer type basic logic here (switch statement or if/else)
return _customer.Type == CustomerType.Business;
}
}
}
public CustomerForm: WinForm
{
private CustomerPresenter _customerPresenter;
public CustomerForm(){};
public CustomerForm(Customer customer)
{
_customerPresenter = new CustomerPresenter(customer);
}
private void CustomerForm_Load(object sender, EventArgs e)
{
_someButton.DataBindings.Add("Enabled",_customerPresenter,"EnableUI");
}
}

The solution should be driven by data, not your code.
So if you tag various controls as being visible in state "A", "B", or "C", then a single method could look at its state and know which controls to make visible or not.
You know you did it right when adding new controls for state "D" takes no code changes aside from those required to add the controls themselves.
You might also look at breaking the form down into 4 sub-forms, shared, sub-form a, sub-b, then displaying both "Shared" and "Sub-a" together on a parent form ...

Related

ObservableCollection and Repository pattern in MVVM - How to relate them, and a case for the "Update" method

My Desktop WPF application has a repository (of type Person) which resides in the Model layer, and is called by a ViewModel which has a PersonList property which is databound to a DataGrid.
When I open my Application, the list is shown by default. During initialization, the following code applies:
public class PersonScreenViewModel : ViewModelBase
{
PersonRepository _person_repository;
public ObservableCollection<Person> PersonList { get; set; }
public PersonScreenViewModel() {
_repositorio_pacientes = new RepositorioPacientes();
PersonList = new ObservableCollection<Person>(_person_repository.GetAll());
}
// ... ///
}
My doubts are based on some difficulty to understand how to implement "Save / Update" method(s).
Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ]". So, the most logical thing would be to databind the repository itself to the DataGrid. That could be done if I created a class which inherit from ObservableCollection and implements repository logic. Currently, what I do is take a copy of the repository items, using _repo.GetAll(), and work in that copy, having to commit back after my changes are done.
Specifically, my workflow involves selecting a row in the DataGrid, changing some properties of the selected object, and commiting these changes, expecting that the same object is persisted with the new property values.
Usually, if you take an object in a collection and modify it, you don't need to "update" anything, since you already changed the object itself.
The question is: "How can I data bind my view to the repository itself? Should the repo inherit from ObservableCollection? How is it supposed to be done? Is some part of my reasoning flawed?"
It is important to say that my application is not data-oriented, the Person class is very basic (POCO marked as [Serializable], with a few properties), and my repository uses plain XML serialization and the filesystem structure.
Thanks for reading!
"Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ".
What you originally have is sort of correct. First of all ObservableCollection works perfectly with the View because every add/update/delete will automatically propagate back to the user interface. If you implemented it with repository, then you would have to go call the database reload the control bound to your repository
"How can I data bind my view to the repository itself? Should the repo
inherit from ObservableCollection? How is it supposed to be done? Is
some part of my reasoning flawed?"
You don't want to data bind the Repository to the DataGrid itself, because you lose caching and every time the user loads the user control you always have a trip back to your database.
You don't want to inherit a repository to an ObservableCollection, ObservableCollection has more overhead vs simple IEnumerable given you already database returned you a collection already.
You always don't want ObservableCollection as your collection for your data because it is expensive. A simple enumerable of data is enough depending on your scenario (Read-only data).
In my personal opinion, what you are currently doing is correct... it is generally good practice to have some separation between the various layers of your application; Models, View Models, Views and DataAccess (sometimes combined into Models). Having said that, it really depends on your application... it might not be worth doing this on small applications as it adds a lot of code and time to set up and maintain.
However, the main reasons for providing this separation (called separation of concerns) is to enable unit tests to be able to test the individual layers without concerning the other layers. For example, if we wanted to write unit tests for our view models, we wouldn't want to test their functionality on the actual data objects in the database. If we have this separation (through the use of interfaces) then we can simply mock up data objects to use during these tests.
Another reason, although less common in practice, is to enable whole layers to be 'swapped out' without affecting the code in the other layers. Examples of this would include changing the database used in the application, or maybe changing the views from a desktop application into web pages in a web application. If we have separate layers, then these changes won't affect the other layers.
So to answer your question directly, I wouldn't bind your views to the repositories at all... keep your current separation. After all, how long does it take to copy a collection sourced from the database into a view collection property?
UPDATE >>>
I'm not sure that I fully understand the question in your comment. I'm guessing that you are binding your PersonList property in your view model to the DataGrid.ItemsSource property to display the data. Any changes made in the DataGrid should affect the items in your PersonList. If you were to add a 'Save' Button, then you could update the database in that click or command handler.
If you were enquiring how to find out which elements had been changed, there are several methods for accomplishing this. There is a good tip in the How to get only modified Items from WPF Data Grid post here, but I prefer to use a duplicate collection and just compare them to find the changed elements (you'd need to implement the Equals method for this to work).
Please let me know if that does not answer your question.

Should I dependency inject? How do I do it?

Okay, so I am working with Microsoft Prism in WPF using a MVVMC(or MVCVM) pattern.
In my ChatModule I have a series of Views, ViewModels, and one Controller.
For the Views I have
ChatAreaView - Displays the chat messages that come in to be read. This is hosted inside of a TabControl region so that I can have chat windows between the user and other users, or maybe file transfer windows, etc.
UserAreaView - This is a list of the users. Right clicking has context menu to interact with them... like sending a file or whispering.
MessageAreaView - This is where the user types in messages to be sent to all of the others.
For each view, I have a corresponding ViewModel. ChatAreaViewModel, UserAreaViewModel and MessageAreaViewModel. These ViewModels essentially only contain properties.
For example, the UserAreaViewModel defines a struct of type User which is essentially just a Name. Actually this is defined outside of the class, but still... it uses it. It has an ObservableCollection to store a list of all the Users who are currently connected. It also has ICommand properties defined to interact with the user. Right now I have SendFile, Whisper and Nudge... with intent on adding more in the future.
The Controller creates these views and ViewModels, and marriages them. It news them up, assigns the ViewModel as the corresponding View's DataContext, and sets all the initial properties of the ViewModel. Over the lifetime of the module, it will react to user interaction and execute DelegateCommands that it has assigned to each of the ViewModel's ICommand properties. These will further alter the state of the properties in a ViewModel.
I am using the actual types of Views and ViewModels, instead of interfaces, like such.
#region Views
ChatAreaView viewChatArea;
UserListView viewUserArea;
MessageView viewMessageArea;
LoginPromptView viewLoginPrompt;
#endregion
#region ViewModels
ChatAreaViewModel viewModelChatArea;
UserAreaViewModel viewModelUserArea;
MessageAreaViewModel viewModelMessageArea;
LoginPromptViewModel viewModelLoginPrompt;
#endregion
Would things be a lot more neat, less coupled if I defined interfaces for the Views and ViewModels, and operated on these interfaces within the controller instead of the concrete implementations? Could I then just register them with my Container in the Module class(which is essentially the root of each Module)?
What do I have to gain from doing this? How would I implement an interface for each view to distinguish them from the others? They don't really do ANYTHING except have XAML... and teh ViewModel's don't really do anything either except have certain properties. And those properties might be subject to change. On the UserAreaViewModel for instance, I will definitely want to add more commands so a user can interact with another user in different ways.
Can somebody help me out here? In my mind I'm thinking I should be abstracting this stuff, but I don't really know a logical way I should be going about it, or even if it's a wise idea to do so. What do I have to gain?
Thank you for your time. The below image is an example of what I'm working on. Ignore the Add new Item button and the styling of everything... that's not what I'm working on right now.
loosely coupled - can replace an entire class with altogether different implementation in future.
independent development.. can inject a dummy UI / view until final UI gets ready. two pieces can evolve at the same time (after having a common contract).
no need to add references to the modules (implementing the view). can use ConfigurationModuleCatalog to discover types from config file.

How to handle bindable application wide variables in a WPF MVVM application?

I am writing a fairly large scale WPF desktop application using the MVVM pattern. I have been stuck for a while on getting my common properties to update in a View other than the one that updated it.
I have a RibbonWindow MainView that contains a ContentControl that displays the remaining Views one at a time dependant on the user's selection. I have a BaseViewModel class that all the ViewModels extend. Among other things, this class exposes the INotifyPropertyChanged interface and contains a static property of type CommonDataStore. This class also implements the INotifyPropertyChanged interface and contains the properties that are to be available to every ViewModel.
Now, although I can access and successfully update the CommonDataStore properties from any ViewModel, the problem is that the WPF Framework will only notify properties that have changed in the current View. Therefore, although the common values have been updated in other ViewModels, their associated Views do not get updated.
One example from my application is the login screen: As the user logs in, my LogInView updates with the new information (ie. full name) from the database, but the user details in the MainView do not.
After reading a few other posts, I also tried implementing the CommonDataStore class as a Singleton, but that didn't help. I could also just pass a reference to this common data object to the constructor of each ViewModel from the MainViewModel, but I'm not sure if this is the right way to go.
I have also discovered that in WPF, static properties are treated a bit like constant values. It seems that they just read the value once.
So anyway it's clear, my attempts have all failed. I was wondering what the standard way of doing this was? In particular, I need to be able to bind to the common properties and have all of my ViewModels and Views update when any common value is changed. Any help would be greatly appreciated. Many thanks in advance.
Edit >> Really? No one uses application wide variables in an MVVM WPF application?
I have now removed the static part of the Common property declaration and am simply passing a copy into each ViewModel individually. This seems to work, but I'd really like to know how others approach this situation. Please answer by simply letting me know how you organise this application wide data.
I have done something similar to what you describe last. I have class called SecurityContext that holds some of the application-wide data. One instance is created when the application starts up and then that instance is passed into the constructors of all the ViewModels through dependency-injection. I have a base class for ViewModels which exposes that object through a regular instance property (implementing INotifyPropertyChanged).
Have you looked into implementing the Observer Pattern? We have done so with IObservable and IObserver. This describes the "IObservable/IObserver Development Model" as follows:
The IObservable/IObserver development model provides an alternative to using input and output adapters as the producer and consumer of event sources and sinks. This model is based on the IObservable/IObserver design pattern in which an observer is any object that wishes to be notified when the state of another object changes, and an observable is any object whose state may be of interest, and in whom another object may register an interest. For example, in a publication-subscription application, the observable is the publisher, and the observer is the subscriber object. For more information, see Exploring the Observer Design Pattern on MSDN.

Is it just me, or is WPF a mess of databinding and custom IValueConverters?

Seriously, it seems like every time I want to make my UI elements talk to each other, I end up coding a new, custom, IValueConverter :(. Someone tell me that I'm doing it wrong, please!
Examples:
I wanted a button to be enabled only if my textbox contained a valid URI. Great, time to code up a UriIsValidConverter!
Oh oops, I also wanted to disable it while I'm processing something. I guess now I need to code up a UriIsValidAndBoolIsFalseMultiConverter!
I want to display a list of files in a certain directory (specified by a textbox) inside a listbox. I guess I need a DirectoryPathToFileList converter!
Oh hey, I want icons for each of those files in the listview. Time for a FileInfoToBitmap converter!
I want my status to be red if my status-string contains "Error", and green otherwise. Yay, I get to code up a StatusStringToSolidColorBrushConverter!
I'm really thinking this isn't that much better than the old Windows Forms method of just wiring up everything manually using TextChanged events (or whatever). Which I guess is still an option. Is that what people actually do, perhaps, and I'm trying too hard to make everything fit into the databinding paradigm?
So yeah, please tell me if this is really how WPF coding is---or if I'm doing it wrong, and if so, what I should be doing.
Your approach is perfectly valid (though I would use a multibinding for the second example, rather than a such a specialised converter), though by placing all your logic into the XAML you are producing very high coupling between the way the application looks and the way that it behaves, because of this you may want to look into the MVVM pattern to separate those things out.
Under the MVVM pattern your XAML (the view) just contains very simple data bindings into a ViewModel which handles all the logic and updates the view through the INotifyPropertyChanged interface. The code for your third example may look something like:
public class DirectoryManagerViewModel : INotifyPropertyChanged
{
private string _directory;
public string Directory
{
get { reutrn _directory; }
set
{
if (_directory != value)
{
_directory = value;
OnPropertyChanged("Directory");
if (IsValidDirectory(value))
{
PopulateFiles();
}
}
}
}
public ObservableCollection<FileViewModel> Files { get; private set; }
private bool IsValidDirectory(string directory)
{
//return if the directory exists etc.
}
private bool PopulateFiles()
{
//Populate Files with files in directory
}
}
Where FileViewModel is another view model which contains the name and the icon for a file.
The advantage of this approach is that the ViewModels can be reused with other views and other technologies such as ASP.NET or Winforms so you are not locked into the WPF stack. (alos if you work in an environment where there are designers responsible for the look and developers responsible for the behaviour, this helps define those boundaries)
At the end of the day though this logic does need to go somewhere and while there are better and worse ways to architect your application you are still going to be writing code that takes a string and converts it into a series of filenames and icons somewhere.
First, you might want to start by reading about the Model-View-ViewModel pattern (MVVM). Josh Smith had a fantastic article in MSDN Magazine recently. MVVM and WPF go perfectly together. Done right, you won't need IValueConverters so much. The way that you are going about it now is causing a very tight coupling between your visualization and your application actions. MVVM is designed to decouple these elements.
In this context, your view model will track state for you. Your button will be enabled if the CanExecute method on a certain ICommand in your view model returns true. This same concept can handle disabling the button when processing something.
You want to display a list of files in a certain directory that is specified inside a listbox? Have a DirectoryViewModel view model that will handle providing the list of files to the view by binding to the view model. The display of the files can be specified with a DataTemplate specified in XAML with no code behind. This same concept can handle providing the icons to the view whose display can be specified in the template.
You want your status to be red if a status message contains "Error" and green otherwise? Let a view model handle determining the state and let the view bind to that state and now you only need an IStateConverter to convert the state to red or green appropriately (this is one of many ways to handle this problem in the MVVM context).
Get in the habit of keep data and state separate from your view and your applications will be loosely coupled, easier to design and maintain, and easier to test.
Don't know if you are wrong, just making it a lot harder than it has to be!
I use MVVM, so where you are writing customer converters, I provide a bindable property on the view model that tells the view what to do. For example:
To display a list of files, I provide a collection that contains that list.
If I want icons the object in that collection has a icon property
If I want a status to be red or green I provide a StatusColorbrush property.
By moving this logic into the view model, I get:
much simpler Xaml.
can test my view logic without the view.
This approach uses one of the strong points of WPF, it's binding capabilities.

MVVM Experts need your opinion on MVVM and Dataforms

as far as I understand the ViewModel should abstract the model from the view and add additional logic to handle the presentation stuff.
My question is:
How would I create a dataform that is suppose to handle user input for an order and details at once.
It should present fields for entering the orders as well as the fields for 1 detail.
My Model would have an object for an order which contains a list of OrderDetails.
How would look my ViewModel for my OrderEntryForm like?
Would I have an OrderViewModel and an OrderDetailViewModel and my
my OrderEntryForm would contain a property of OrderViewModel and one for OrderDetailViewModel? (nesting ViewModels?)
How would validation be handled in this case? Since Validation should go close to the model?
Especially when I work with RIA-Service...
Wouldn't it make more sense to put it in the ViewModel?
How far would you abstract the Model from the ViewModel?
Example:
private DateTime _OrderDate;
public DateTime OrderDate
{
get { return _OrderDate; }
set
{
if (_OrderDate != value)
{
_OrderDate = value;
OnPropertyChanged("OrderDate");
}
}
}
this would mean I have to map the ViewModel-Property to Model-Properties. Cannot leverage Validation-Logic from the Model here...
This example:
public DateTime OrderDate
{
get { return Model.OrderDate; }
set
{
if (Model.OrderDate != value)
{
Model.OrderDate = value;
OnPropertyChanged("OrderDate");
}
}
}
would requiere to pass in a Model. Have the access to the validation logic of the model but also a coupling...
Most examples on the web show dataforms which use ViewModel's that a just a representation of the tables not a real abstraction...
I know and I saw this
stackoverflow.com/questions/744474/combining-net-ria-services-and-mvvm-in-silverlight-3-0
I also read nikhils blogpost on this but this handles also only Products straight mapping from the tables of the database... =(
I know alot of questions...
What are your opinions on that topic?
How would you handle complex dataforms?
Chris,
I have had the same issue and end up implementing it in a crappy way :-( (two vieModels one per view, but passing the parent to the child View... bad stuff).
From my error I learn that next time I would give a try to:
Generate a single ViewModel, but in the child view pass a detail entity in the datacontext (this detail entity does not have to match with the proxy generated entities, maybe is a container of that entities).
Generate a singleton controller class: this class won't be exposed to the view, it will be transparent for the view, just the detail view model will ask the controller for that dependant data instead of going to the DAL.
Not sure if this are going to be clean solutions, have to give a try and fail :).
I agree with you... there are not real samples with this kind of scenarios.
What do you think?
Thanks
Braulio
PS: About validation, if we create our own super entities, we can there define our validation, in my case I have tried as well extending the entities using partial cases and then I can have an entity myPhoneNumberDetail with my special validation.
I personally think there are no hard and fast rules... well, there is one - be pragmatic.
Pragmatically speaking, a view model is a model, and so is a data model. Both are classes, independent of the UI, and surface state as properties, operations as methods, and notifications as events. The thing that I think in my mind differentiates them is how general they are. I see a model as generally usable across multiple views, vs. a view model optimized for a particular view.
I would personally never abstract for the sake of abstracting. I would never surface top-level properties for every model property and implement it by delegating to an underlying model. This increases work. It increases the amount of code to be tested. It requires propagation of metadata, change notifications etc. If there is some actual logic to add, then yes, there would be properties on the view model I'd expose and delegate to the underlying model as appropriate. Even there I'd ask if it is reasonable/appropriate to expose those as computed properties on the model (view model and data model are both models).
As far as surfacing DAL types directly vs. not, that in my mind is somewhat orthogonal. It depends on other factors - how much do you want to abstract the DAL, how useful a DAL type is - for example, if a DAL type has a lot of foreign keys, a presentation model equivalent or projection might be more useful where there is some denormalization done. Sometimes security might be the reason to write a presentation model/projection - eg. I don't want to send email addresses to the client, and instead want an alternate representation of email addresses.
In my sample, I used a DAL type directly, to simplify and not have an overload of concepts in a single sample. I do want to blog about presentation models and projections in a dedicated manner... and so didn't want to mix posts of viewmodel and .net ria services with presentation model concepts at the same time.
As is so often, with patterns, it really depends. The ViewModel can expose the underlying model, and there is no hard and fast rule that says you "must" hide everything and delegate. I have spoken to many folks that are strict adherents to LOD and still they agree that in the case of UI binding, it does not apply.
Now in the case of whether that model is a DTO or not there you will find a lot of differing opinions. Some believe that the only thing that should ever be on the client is a pure projection i.e. a DTO with all logic living on the server, while others believe that that moving entities between the tiers is fine. That would be an discussion for a different post. :-)
In general the guideline that i would recommend is always at least have a high-level VM which can be used for screen state, etc.
As far as child models, like OrderDetail, then if the child model is sufficent to just bind to then just expose it directly. Now one thing to consider is around notification, if you model is not implementing INPC than you may have no choice but to wrap it in order for binding to properly work.
Even if it implements INPC there may be view-specific concerns that that model does not contain, but which are required to for the view to function. In that case I would use simple aggregation and create an OrderDetailVM that directly exposes the underlying OrderDetail and adds additional properties.
For example
public class OrderDetailViewModel
{
public OrderDetail OrderDetail {get;set;}
public bool IsValid {get;set;}
}
Where IsValid is checking some screen-specific logic.
It really depends though on how much encapsulation you want to achieve. I wouldn't find anything wrong with using a delegation model. Depending on the complexity though it might get unwieldy, for example imagine if OrderDetail had additional children, etc.
HTH
Glenn
To clarify, the VM is an abstraction of the Model, not of the View and not the other way around.
You can certainly use multiple VMs to correspond to discrete portions of your View. If you're not going to need separate VMs for Order and Details, you can just have an OrderAndDetialsViewModel that contains everything, and the whole View will bind straight to that. This is where the abstraction comes in.
You are right, that your model's validation logic is going to be distinct from your ViewModel's validation logic, if you put any in there. In no case will the validation be in the View.
I'm not sure I follow your second example. What is the Model object? Your VM may know about the Model(s) from which it is composed, but it is not going to expose it/them as such directly to the View.
I hope this helps somewhat. Please let me know if there is any part of your post that I failed to address.

Resources