Restrict Silverlight/WPF Behavior visibility - wpf

In Silverlight (and probably WPF), when I define a System.Windows.Interactivity.Behavior<T> for e.g. an ItemsControl, like
public class SomeAwesomaticBehavior : Behavior<ItemsControl>
{
}
it will appear in Visual Studio's XAML editor (and probably in the Designer too) even for ordinary, non-Items-Controls and throw nasty runtime exceptions. This is contrary to Attached Properties which will appear only for intended types.
Is there a way to restrict that visibility? Some magic attribute maybe (although that would be a redundant declaration)?
If there is no way today, I hope there will be so in the future? Because it surely does confuse co-workers and designer folks when a lot of Behaviors pop up that don't have anything to do with the current object.
Update: I have filed uservoice items.
Silverlight: http://dotnet.uservoice.com/forums/4325-silverlight-feature-suggestions/suggestions/1224253-restrict-behavior-visibility?ref=title
WPF: http://dotnet.uservoice.com/forums/40583-wpf-feature-suggestions/suggestions/1224259-restrict-behavior-visibility?ref=title

#HeRz you are correct, there is no way to filter behaviors by their targeted type. Blend (and probably vs designer) use reflection to find all of the types you create which inherit from base type Behavior and displays them in the assets list.
Blend will prevent you from dragging a behavior or trigger onto an item which it is not intended. So that should help prevent their misuse.
I usually try to write behaviors as reusable pieces of code, not scoped to a specific case. They are simply tools with specific purposes.

Related

How does the VS Wpf Designer instantiate and limit execution of VIewModel code?

The WPF designer has a tough job to do. In order to show you a life view of your screen or component it has to execute code but, since you do not control the designer, it has to do this without producing any side effects.
So how does it do that? What are the rules around execution?
What if the view's code-behind code does logging to a file or a service?
What if the code-behind calls MessageBox.Show?
What if the code-behind doesn't have an empty default constructor?
I've hit situations before where I had a default constructor that was checking GetIsInDesignMode and creating and assigning a DataContext if false, and still the designer wasn't rendering correctly. Is there some sort of stack-depth limit?
What are the limitations?
it has to do this without producing any side effects
No, the designer is not that smart. If IsDesignTimeCreatable is specified, it will execute all code in a public parameterless constructor and in properties accessed by bindings. Specifically, it will popup message boxes, write to files, etc -- or throw exceptions trying (just try it yourself).
If you don't have a public parameterless constructor, it can't create an instance, so no code will run.
Regarding your question about "stack depth limit", I know of no such limitation. If you have a specific case where it's not working, I suggest you ask a specific question about that case.
In most cases where the designer fails it is because of an exception or other non-data-related problems (such as missing design-time resources). You should definitely guard code you don't want called during design-time using DesignerProperties.GetIsInDesignMode (I usually add a property IsInDesignMode to the base view model).
This is not exactly answering your question, but to be honest 'how does it work' is not a very specific question.
However rather than dropping this check in to your code-behind, are you aware that you can add something like this to your Xaml?
d:DataContext="{Binding Source={d:DesignInstance Type=namespace:className, IsDesignTimeCreatable=True}}"
This means that you can make a design-time version of your class, e.g. CalculatorDesign :
ICalculator, reference that in the Xaml, and each time you change and compile the design-time class the view will update within VS without running any code or having complicated logic in code-behind.

Custom xaml markup template for user control

Is it possible to customize default user control markup in xaml ?
Let's say i have a user control named MyUserControl.
What I would like to know - is it possible, when I type
<controls:MyUserControl -and then type- >
instead of just ending up with
<controls:MyUserControl ></controls:MyUserControl>
to have
<controls:MyUserControl DependencyProperty="1" DependencyProperty="Person" ... ></controls:MyUserControl>'
Basically I want to create a custom template that would be used when auto-completing user control in xaml editor.
Purpose is to show the user available properties right away ( user that wants to use some control that he did not use before can see how to change important properties without browsing all possible properties on user control )
As far as I am aware, there is no simple way to do that, but I'd say that it was unadvisable to try to do that anyway. You said that you want to show the user available properties right away, but that is what Microsoft's Intellisense in Visual Studio is for. Once you have declared your DependencyPropertys, they'll automatically appear in a popup when a user is using your class.
As the .NET controls do not do what you suggest, then yours shouldn't really do that either. You're more likely to confuse developers with this unusual behaviour and they might even leave these added and quite possibly unwanted properties because they don't know any better. Your best bet to help users of your code is to implement it in as standard a way as possible, so that everything will work as expected.
You know, the most annoying bugs are caused from problems with code that was meant to help us.

Pros and cons of having a WPF specifics in the view model

I'm having trouble deciding what to think about this piece of code:
public SolidColorBrush Brush
{
get { return IsValid ? _validItemBrush : _invalidItemBrush; }
}
It is part of a view model in my current project and as you can imagine, the Brush will be bound to some text elements in the UI, to indicate (in-)validity of other pieces of data, in an otherwise fairly simple and straightforward dialog.
The proponents of this piece of code say that since we're using WPF, we might as well allow for some simple WPF specific constructs in the view model.
The opponents say that this violates Separation of Concerns, as it clearly dictates style which should be taken care of solely by the view.
Please share your arguments, and if you're not happy with the code above, please share your ideas around alternative solutions. (I'm particularly interested in what you have to say about using DataTemplates).
Is it possible that there is one solution that could be considered best practice?
Personally, I would have the two brushes be defined in XAML, and have the controls that use them switch brushes (in xaml) based on the IsValid property. This could be done very easily with DataTriggers, or even a single IValueConverter - the converter could take 2 brushes and a boolean and swap between them fairly easily.
This keeps the business logic presentation-neutral - a "Brush" is very specific to a specific form of presentation, and a pure View choice. Hard-coding this into the ViewModel violates the single responsibility principle as well as is not a clean separation of concerns.
I would very much keep this in the View, and switch based on the IsValid (bound) property that is ViewModel specific.
While there are circumstances where I might use WPF constructs in the view model, this isn't one of them. Here's why:
It's harder to change. If you define brushes as resources and use them in styles, changing your application's color scheme can simply be a matter of loading a different resource dictionary. If you hard-code color values in your view models, you have a lot of different things to change if it turns out your end users need different colors.
It's harder to test. If you want to write a unit test that checks to see if a property is returning the right brush, you have to create a brush in your unit test and compare the values of the two, since it's a reference type.
In many, maybe even most cases, it doesn't make the code simpler or easier to maintain. You're pretty likely to already be using a style (assuming that you are conversant with styles), since they make just about everything in WPF easier. Binding IsValid to brush colors is just a matter of adding a DataTrigger to a style. Which is where anyone maintaining this code would expect to find it.
There are certainly times when I do use WPF constructs in the view model - for instance, long ago stopped wondering if it was problem if a view model exposed a property of type Visibility. Note that none of the above concerns apply to that case.
In cases like yours where it's purely aesthetic I use Triggers or the Visual State Manager to change colors.
Sometimes I do use colors in my ViewModels, but only if its part of my software spec (e.g., the color of the chart displaying a patient's CO2 depends on localization). In that case, I use a Color struct bound property, allowing the View to use the Color for a SolidColorBrush, a GradientStop, or whatever it wants. I initially used a string in #AARRGGBB format to completely remove the WPF dependency but my more seasoned co-workers didn't like that.

Interactivity.Behavior<T> vs attached properties

I'm trying to find some differences between these approaches. Is there any situation where behaviors are used and the same functionality could not be done with attached properties?
No. Behaviors are basically just a much nicer abstraction on top of attached properties.
By using Behavior<T>, you gain access to the AssociatedObject directly, as well as the ability to attach and detach the behavior, easily, at runtime.
You could do this with attached properties, but it would require adding a lot of extra plumbing.
I tend to use Behaviors to add functionality which makes visible changes. Whereas I use attached properties to add additional information to an object which is subsequently used by other objects.
E.g. Grid.Row makes a good attached property, as it's used by the Grid and not the target. On the other hand, AutoCorrect would make a good behaviour, as this will make visible changes on the object.
Behaviors are based on attached properties. That means if you can't find specific behavior - you write your own, either based on behaviors framework provided by Blend or by creating your own AP...
I always thought that behaviors are great evidence of attached properties power. Just incredible what you can get with them.
This is not the answer. But the best explanation I can find on this topic
https://web.archive.org/web/20180208143035/http://briannoyesblog.azurewebsites.net/2012/12/20/attached-behaviors-vs-attached-properties-vs-blend-behaviors/
Brian Noyes in his articles clearly describes the differences between each of the concepts.

WPF control inheritance

I've read in a blog the following sentence:
The first rule of WPF:
Avoid control inheritance.
I've seen similar things in other places as well.
However, I fail to understand the logic.
Moreover, I see suggestions here in StackOverflow that involves inheriting WPF controls (see the replies to my previous question for example).
I would like to understand why (and if) control inheritance should be avoided.
WPF controls are "lookless". In other words, their look is separated from their behavior. More often than not, you actually want to customize the look - not the behavior. Unlike the world of Winforms, this does not require you to inherit a new control and override rendering logic. Instead, you set some properties on the control, resorting to overriding the template itself if you can't get the look you want from other properties.
Note that "avoid" means just that. Avoid inheritance if you can. In cases where you need to modify behavior, inheritance may well be the best option.
The blog from the link also states in the end that:
"With Styles, Templates, Decorators and attached properties and behaviors you can accomplish most of the things that you used to have to roll a new control for."
That is true. However, were it always true, the wpftoolkit team wouldn't have made their DataGrid as a subclass of MultiSelector.
Judge each case separately, I would say. Also check this answer.

Resources