D J has a good answer, though I'd like to insert some additional thoughts to this discussion.
In my experience, view behaviors (whether code-behind, attached behaviors, blend behaviors, or custom control logic) are often useful when the view does not depend on a view-model to function properly. If a view (UserControl
, Window
, Page
, etc.) does not logically make sense in the absence of a view-model, it might make more sense to remove behavior from the view and move it to the view-model.
While we can do pretty much anything under the sun with all types of behaviors, it is often not wise to. MVVM, for good reason, limits what we should do so that we can observe separation of concerns to improve our application's cohesiveness and to decouple our classes. These two things are what software maintainability is all about, and these concepts become increasingly important as the application grows into enterprise software.
It is important to think about the concerns that the behavior has. Understanding this will help us find a properly suited place for it. Here are some questions to help know where it belongs:
Does the behavior interact with a business domain model (this is the first 'M' in MVVM)?
Behavior that has a dependency (even a loosely coupled one) on a domain model should likely belong in the view-model (or service), and not in the view. For instance, if the behavior needs to save to or read from an external device (e.g. a database), it has a dependency that the view should never have. Wrap this logic in a service function.
Or if not using a heavily layered architecture, put this inside of a view-model.
Does the behavior interact with application services, domain services, infrastructure services, etc.?
For the same reasons as the prior answer, the behavior likely belongs in the view-model or a service class. The view should have no explicit knowledge of services or domain model objects as it would muddy up its responsibilities (or concerns) that the view has. A view should only be concerned the visual/physical aspect of the user UI. Many views should define a contract (i.e. a view-model interface) that it binds to in order to operate correctly.
Will the behavior need to be reused across different views of the same kind?
This is a bit of a tricky question. Many times we foresee being able to have a different presentation for the same content. In effect, the view in these cases is a thin wrapper around some structure. For instance, suppose for a e-mail application we have a summarized view for received e-mails as well as a detailed view. Both views might need to support the same behavior (e.g. delete, reply, forward). Because we are reusing the behavior across different views of the same kind, then the behavior should belong in a common, reusable place. View-model logic is a good place for this.
Will the behavior need to be reused across views of different kinds?
When the behavior needs to be reused across different kinds of views (e.g. TextBox
, ComboBox
), we likely need an attached behavior. Usually, we can know this because the views are so diverse that it is not possible for them to share a view-model interface. Given that the behavior is concerned with view-related responsibilities, then custom control logic, code-behind, attached behaviors, or blend behaviors are all suitable places.