Is it an antipattern to use both traditional click events and ICommand? - c#

Generally, I think it's good practice to use ICommands to handle button clicks that need to do something (such as save user input). However, when the button does something strictly on the UI, like open a modal dialog, the view model doesn't need to handle that, or even be aware it happened. In such cases, it seems like it makes more sense to just use the button's Click event handler, but mixing and matching like that seems like a potential anti-pattern. Am I correct in thinking so?
For example:
var openModalButton = new Button();
openModalButton.Click += OnModalButtonClick;
//Elsewhere in the view...
var saveInputButton = new Button { Command = _vm.SaveInput };
It's not inherently clear by looking at the code why one uses a command, and why one uses a click event.

Jedediah,
I usually do as you and mix and match. Usually (for me) there is only 1 or 2 cases like this, and the idea of patterns and architecture is to make the code easier to read and simplify things. Adding a lot of code just to ensure the MVVM pattern is followed seems like it complicates things in this case. That said, the way I've seen this usually handled is bind the button to your ViewModel with ICommand, and then use a "mediator" or "service" to launch the dialog. You could do a Google Search on: "HOw to handle opening a modal dialog the mvvm way " and/or see:
Open dialog in WPF MVVM
The "pretty" way to make a modal dialog in WPF with Prism and MVVM Pattern
Handling Dialogs in WPF with MVVM
Good luck!
Dave

Of course consistency is important as Robin pointed out. However there are scenarios when you'd not want the ViewModel to be involved. Then there's no choice and I think it is much better to break consistency here but not to break the pattern (MVVM) by handling stuff in the ViewModel that is not its job.
You took modal dialogs as an example and I do not agree that the ViewModel should not know about it. Of course the ViewModel is not allowed to directly open that dialog, settings its owner and the likes. But the dialog most probably is part of the workflow and it's just fine to know about the current state of the workflow in the ViewModel. So there should be a layer in between. A service or something similar that allows you to say "I want to show the UI for X" and that solves this by using a modal dialog. The ViewModel doesn't know about the modal dialog but it knows the current state, for example that it is asking the user whether to save changes. Of course this requires some kind of infrastructure handling the special cases and tricky parts. MVVM frameworks offer solutions for this.
If that sounds like overkill for your application simply put that event handling in the code behind of the view. It is not beautiful style but it does not break the MVVM pattern.
In one phrase: Better to mix than to violate the pattern.

I think it is an anti pattern, or not very cool thing at least,first because you're mixing the two approaches and that's not consistent, secondly because I believe that that needs always to be handled in a Command instead of an Event handler, why ?
the view model doesn't need to handle that, or even be aware it
happened. In such cases, it seems like it makes more sense to just use
the button's Click event handler
Not really, additionally to the fact that Commands help you separate your object from the logic that executes the Command thus it makes it loosely coupled, but it also help enhancing the reusability of your code, for instance someone in the future may want to change that button into a whole new control that might have a different event, and different args for the corresponding event ...
and that breaks your code, using a command however is better and is always compatible and reusable.
Moreover, Laurent Bunion explains in this article how Events are problematic :
For all their utility, event handlers have one problematic side
effect: they can create a tight coupling between the instance that
exposes the event and the instance that subscribes to it. The system
needs to keep track of event handlers so that they can be executed
when the event is raised, but the strong link this creates might
prevent garbage collection. Of course, this isn’t an issue if the
event handler is a static method, but it is not always possible to
handle all events with static methods only. This is a frequent cause
for memory leaks in .NET.
Another consequence of the tight coupling between an event and its
handler is that the event handler for a UI element declared in XAML
must be found in the attached code-behind file. If it is not there (or
if there is no attached code-behind file), the compilation will fail
with an error. This is especially an issue when working with list
controls and associated DataTemplates. When an element of the template
must be actuated, an event handler can be defined, but as a
consequence, the DataTemplate cannot be moved into an external
ResourceDictionary.

Related

Registering message recipients at the Application level in MVVM Light from XAML?

Specifically, in this case the Application itself would be the recipient. My thought process is that this would allow for the least possible linkage between Views and View-Models when dealing with the scenario where a new View would be created: They would deal strictly in messages and the App level of the WPF application would handle these messages, creating new views (and implicitly view models through the DataContext of those Views) as appropriate.
This is straightforward enough, as far as I can tell, if I go into the codebehind (app.xaml.cs). However, I would ideally like to handle this message recipient registration in the xaml if at all possible since the behavior is fairly straightforward, all it would really be doing is calling ShowDialog for the appropriate View (I don't think any further handling would be needed, but I may be forgetting something).
For the life of me, I can't think of a way to avoid the codebehind though (I know that MVVM does not really forbid the use of codebehind and I'm making things harder on myself with this, but I think it would make for better code organization if it is possible without violating some other MVVM principle). I thought I had it when I considered the use of System.Windows.Interactivity and tying an EventTrigger to the Startup event of the Application class, but was foiled when I discovered that it needs to extend DependencyObject for that to work.
To summarize, my question is twofold:
A. Is it even possible to handle message recipient registration within the app.xaml for the subset of messages that involve the creation of Views.
B. Is this even an appropriate structure to try and apply or am I way off-base with my thoughts on how to organize responsibility for the handling of messages that relate to other views. If it is not an appropriate approach, is there an easier way or a better way?
The View should contain all view-related code and no programme logic - this is MVVM separation. If your view needs to display a message box, this must then be handled by code in the View. This is the same as animation which must be defined in the View but can be easier in the code behind.
MVVMLight messages allow a simple way for a ViewModel to say "I want to show this" and the View to decide how to show it. The View registers to receive the required type of message and deals with the UI part of showing it - be it a MessageBox or other.
A purely XAML, and probably prettier way would be to build a custom message box.
As for part B: I would receive messages where I wanted to handle them.

Is it ok to use click events for small operations in WPF (MVVM)?

I have a WPF application implemented using MVVM. But for some small operations, such as scroll, confirmation box button click, left click operation, right click operation, etc, I am using click events directly in views.
I know MVVM does not recommend this, but is it ok to have such click events or its a bad coding practice while using MVVM? What are pros and cons of using this?
the MVVM pattern gives you:
Seperation of concerns (which is true for all UI patterns)
Unit testing of view logic, by executing the view-model without the view.
Developer-Designer workflow, allowing designers using Blend to work on the same code.
If handling UI events in code behind doesn't prohibit the above, then there is no problem. Personally I use commands if I can, but am not concerned if there is a little code-behind required.
Events can be used, but the problem with allowing codebehind events is that it's a slippery slope. you add one thing, then you add another, and all of a sudden you create actual logic in the codebehind class. (It's even more prominent if you are working with other less experienced programmers in your team).
That's why some programmers prefer, to almost no exceptions, to not write codebehind AT ALL.
Every code that fits the codebehind without being really application-logic code can also be written within a Behavior, which makes the architecture much more strict and simple to define.
If your button does something that is specific to your UI then yes you should use event handlers over commands.
e.g. If you have a button that scrolls a ScrollViewer control to the bottom then it would be bad practice to use an MVVM style command as your ViewModel would need knowledge and direct control of the view. For these situations the view should be self contained.
If your button needs to do something with data then you should use a command and perform the operation in the ViewModel.
I fully agree with #Noam M. Just to extend his answer:
Whether it's violation of MVVM or not depends on what you acually do in eventhandlers. If it's logic that is covered by the view responsibility, it's perfectly ok.
For example, PasswordBox password property cannot be databound, because it is not DependencyProperty and using PasswordChanged eventhander to set viewmodel property is perfectly ok. However, if you wrote password validation against server, that would be violation of mvvm.
I often use Loaded/Unloaded events to call Activate/Deactivate methods on my VM. When I use it too often I create behavior implemented as attached property, that does it for me, so I don't have to repeat the same code in code behind multiple times
I often use DataGrid's events in codebehind, like sorting etc.
I use TextBox.GotFocus event to select all text. Again, I create behavior when I need to reuse it.
I use codebehind to trigger, or create animations if it would be too complicated in xaml. In that case I just leave comment in xaml for other developers.
In MVVM application not all assets must be strictly written using MVVM. For example I have just written my ModalDialogWindow, where I inject content and buttons. I don't have viewmodel for this control and I do everything from codebehind. However, my application has solid MVVM architecture and I show modal dialogs from my page viewmodels using IDialogService. The ModalDialogWindow does not break testability, blendability, or readbility of my application, because in test I mock the IDialogService anyway and I don't need to test ModalDialogWindow UI itself.

Organization with WinForms

So I've just started developing C# WinForm applications and each project I've been working on seems to be larger and requires more user functionality. If I add all of the functionality to one form, obviously it can get out of control very quickly. My last project I would divide up the functionality into individual Forms, and whenever someone say wanted to perform "Feature1" I would instantiate Feature1 Form and show it as a dialog with the main Form as it's owner (so they couldn't click off it).
I'm just curious of what other methods are out there for keeping code organized within Forms. If you are forced to have tons of features/functionality on a single form is there a good way to keep items organized? I simply hate having a code file with hundreds/thousands of lines long.
The answer may simply be in the design, try to design the UI up front so you can utilize multiple forms?
Another example I faced. I created a Tab Control and had about 5 tabs. Those 5 tabs had tons of features and were all stored in the same CS file. What other options did I have? Create a new custom TabControl class with my specific functionality for that tab in it?
I don't mind reading, so if there are decent articles out there feel free to link them!
The go-to method is a Controller/Presenter. The idea is that the window should only be responsible for actually handling the UI events of its controls, and it should do so by calling methods on a Controller which do the real work for the window. The window can either have the handlers necessary or it may link the UI events directly to Controller methods; the former is usually the easier method, but it can be tempting to sneak in a line of code here or there that really should be in the Controller method. By doing this, you sever the layout and presentation logic in the Form class with the business logic in the Controller.
Mark Hall's suggestion of User Controls is also a good one. By creating UserControl classes for tabs or for common UI control combinations, you sever the logic responsible for laying out that part of the UI from the main form's code, and the control then just "drops in" and the window works with it in a much simpler way. This is a must for implementing custom but reusable controls; the fundamental tenet of DRY is that if you have two lines of code in two different places doing the same job to two different but interchangeable things, those lines of code should be merged into one place.
I have used UserControls in my projects to group functionality into separate objects that can then be added to your Form.
I tend to split my logic code from the UI as recommended. If you do this, you need to be somewhat cautious with how calls are made across the application to avoid Cross Thread Exceptions. I was taught to create delegates and events to update the UI from the logic class, but MSDN of course also has a lot of information on making thread safe calls.
I know this is a late answer, but if anyone still reads this question, another way to reduce the number of lines of code in your form is to use Data Bindings. If you are using properties, Data Bindings make it so that you don't have to constantly write handlers just to do something like PropertyName = textBox.Text;. Data Bindings work with both datasets and objects.

eventaggregator vs services

When developping rather large applications using Prism and MEF/Unity I always reach a point where I should choose between using events, a service or maybe both. And I cannot decide what's most usable. Maybe something is wrong with my architecture (as in this decision shouldn't have to be made in the first place) but I don't see what.
Here's a typical example: my application has a main window and a lot of slave windows that are created on demand by modules or user actions. The application decides what a slave window's chrome looks and behaves like, remembers window placement etc while the content itself is created somewhere in the modules. There are also a lot of user actions resulting in hiding/showing/bringing to front of windows. To achieve all this, I currently have a WindowManager service that listens to CreateWindow/SetWindowState/.. events.
This has benefits:
classes using this only know about IEventAggregator (which they already use most of the time anyway for other events) and the events consumed by WindowManager, not WindowManager itself
classes like ViewModels don't deal with windows directly. Instead they refer to them by their title or id and small event classes that encapsulate just what's needed.
no need for a seperate IWindowManager interface just for the purpose of mocking it in a test
And withdrawals:
WindowManager could be used perfectly standalone, but now it needs to subscribe for events. Or probably better, some other class has to take care of that.
extending it to show a modal dialog is somewhat tricky: if a VM fires an event to show a dialog, it's of utter importance that the Publish call only returns after the dialog was closed
WindowManager is available as a service and it's in the CompositionContainer, why not use it as such anyway?
Using the service directly just shifts benefits/withdrawals around and there doesn't seem to be a clear winner.
Question: what would you use as guidance rules to pick one or the other, or would you rather always pick just one, or both? Is there something particularly wrong in my application design that I have to make this decision?
Events and services are used for different things. You don't have to choose between them, you can use them for different purposes. You would typically use event to notify listeners that something has happened. Example: users changes the font size in the application settings. You would send event to all listeners (e.g. viewmodels) so that the views update. Usually event is kind of thing for which you don't get a response (although you could attach e.g. callback function/action that the event listener would call).
What if your viewmodel needs to open new window? Usually the viewmodel shouldn't care how this new window is opened or whether it is modal or not. In this case it would be easy to use a service:
windowManager.ShowDetailsView();
The WindowManager (which you use through IWindowManager interface) is responsible for displaying the details view. Maybe it is a modal view or maybe there is some kind of slide animation. The point is that the viewmodel that uses IWindowManager doesn't care.
In some cases you might need to receive notification if users clicks Ok or Cancel. You can still use the IWindowManager by having method like this:
public void ShowEditView(Action userSavedChanged, Action userCancelled);
Then just call it from the viewmodel
windowManager.ShowEditView(this.SaveChanges, this.CancelChanges);
// in your viewmodel you have the SaveChanges and CancelChanges methods
private void SaveChanges()
{
// save the changes.
}
Hopefully this all makes some sense. After all it is friday :)

How to create different .cs files

Is there a way in WPF for the events (such as Click) to have the method in a different .cs file rather than the MainWindow.xaml.cs (for instance)? In other words, when i go to select the mouse down event and double click on it to write the method - the method appears in MainWindow.xaml.cs .. is there a way to redirect this to another file? I would need access to all of the attributes/fields that i use (such as textboxes, buttons etc) that are on the MainWindow.....
In my MainWindow.xaml, I' have methods dealing with gotFocus and lostFocus etc. I don't want to be dealing with sockets and connection within the same file (as I feel that is bad design). Correct me if I'm wrong.
If you really wanted to, you could create a Partial Class
to put your event handlers in. It will still be part of the MainWindow class, but it will be in a different file.
That said, a better design would be to move your code for dealing with sockets and connections out into its own class or classes, while leaving the event handling code in MainWindow.xaml.cs. Partial classes aren't really the right tool to use in this case, IMO.
it sounds like what you want to do is use a MVVM design pattern (WPF lends itself very nicely to this, BTW).
here is a good article on MSDN,here is one by Josh Smith, and a google will reveal much more
it sounds like you need to look into commanding as well
If your notion is to remove the dependency between the UI and Codebehind then probably the best idea, since you are using WPF is MVVM pattern. So you that your view doesn't have to know about what is happening when you click on the button etc. Or else you can event think about ICommand to separate the commanding from your code behind. exactly something like #Mead'Dib has recommended.
The other area which you can explore is to think about something like Command Pattern where you can separate the Receiver and invoker. So that you are not tightly coupled with the code behind. So just think about using some kind of pattern that will make you safe when maintenance issues there.

Categories

Resources