What are your 'best practices' for writing custom controls in WPF - wpf

I have started writing some custom controls for a highly visual project. I was wondering what are your 'best practices' when coding WPF custom controls?

If you want your custom control to support direct content like this:
<CustomObject>
Direct content example 1
</CustomObject>
<!-- or -->
<CustomObject>
<Button Content="Direct content example 2" />
</CustomObject>
Then you need to use the ContentPropertyAttribute which tells WPF which property is actually being set when you write xaml like this.
The attribute can be used like this:
[ContentProperty("NameOfProperty")]
public class CustomObject
{
[...]
ContentControl uses this attribute to set the Content property but note that the property can be called anything; the WPF TextBox, for example uses this attribute to set the Text property.
E.G.
[ContentProperty("Text")]
The property also does not have to be a dependency property (see the MSDN documentation example for evidence of this).
Finally, this attribute is specific to the xaml parser and not to ContentControl and can be used with any type which can be seen from the TextBox example above (TextBox does not derive from ContentControl).

Keep property names the same as the property names for built-in Controls if you can do so without changing their meaning.
e.g. if you have a CustomerDisplayer custom control don't call the list of customers Customers, call it ItemsSource.
It might seem counter intuitive at first but it saves a lot of headache in the long run because future programmers can make a lot of assumptions about how a property called ItemsSource will act that they can't necessarily make about a Customers property.

Make sure the control can be re-styled and re-templated without changing the way the control operates. Don't make the control assume that the Listbox and Button are both within the same panel or that there even is a Listbox or Button. Check out the MSDN article on control authoring for some recommendations on how to do this.

Some content controls are dependant on the existence of other controls in their ControlTemplate. Typically this should be documented using the TemplatePart attribute.
The Combobox control, for example, is dependant on the existence of a TextBox and a Popup controls in its template.
This would be documented by placing the attribute on the class like so:
[TemplatePart(name="PART_EditableTextBox", type=typeof(TextBox))]
[TemplatePart(name="PART_Popup", type=typeof(Popup))]
public class Combobox : Selector
{
[...]
The naming convention is "PART_controlIdentifier".
The relevant items would then be given the same names in the control template so that they can be located in the OnApplyTemplate method.
This then allows the control to hook up to events, set properties and call methods on the controls contained in the template.
This attribute is for documentation purposes so that people designing custom control templates (and tools such as Expression Blend) know that the control is dependant on the existence of another.

Learn how to use both dependency properties and routed events (and how they work) so that you can use them effectively in your own control.
Both of these types provide services for integrating your control with the systems built into WPF.
By using these two features in your custom controls you will get the following advantages:
Dependency Properties provide support for databinding, animations and can be used in styles.
Routed Events can be propogated through the visual tree which means that other elements can handle the events.

Related

Custom Control vs Custom Behavior in WPF

What is the difference between Custom Control and Custom Behavior?
Where Custom Control should be used and where Custom Behavior should be. in what ways they can be best used?
Behaviour extends control functionalities
Custom controls customize the visual of Control
A behaviour can be used to extend the functionality of a control to do something that it cannot do on its own without having to modify or re-implement the entire control.
Consider for example the built-in TreeView control in WPF. It has a SelectedItem property that is read-only which means that you cannot two-way bind it to a property of your view model. If you don't want to implement your own custom TreeView control from scratch just because of this - which you probably don't :) - you could solve this by implementing a custom behaviour that sets the value of your source property whenever the value of the target property changes and vice versa. Please refer to the following blog post for more information about this and an example: https://blog.magnusmontin.net/2014/01/30/wpf-using-behaviours-to-bind-to-readonly-properties-in-mvvm/
The following article should also provide a good introduction to attached behvaiours: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF
So a behaviour is basically a piece of code that can be attached to some element in the XAML markup of a view through attached properties and add additional functionality to this element.
A control is a UI component that encapsulates some functionality and has a template such, as for example a Button or a ListBox.
Behaviors encapsulate pieces of functionality into a reusable component.
Custom controls are more work than custom behaviors(White box vs black box)
Some things you have to do a custom control, eg Access Protected members.

Is a custom `RadioButtonList` based on `ListBox` necessary in WPF?

I inherited a project that uses a RadioButtonList which inherits from a ListBox. It was taken off the web (currently cannot find a link to), and contains RadioButtonList.cs (which contains six dependency properties) and RadioButtonList.xaml (which is just styles and control templates).
This control is used in over a hundred places. It causes problems because it is not a complete and professional control. Problems such as, focus issues, keyboard navigation, and so on. (See comments.)
After much research at different times over the last couple years, it seems that this control is really not necessary. All that is needed is to set the GroupName property on a group of radio-buttons. And, the only reason why a RadioButtonList control is used is to help with data-binding a list of options through the inherited ListBox.
1) Is this control really necessary? Is there a better way?
2) Is there a professional control, open-source or otherwise, that will allow me to get the benefits of data-binding without the headaches? (We use Infragistics and DevExpress, but I am not familiar with all the controls these suites offer.)
My Answers
1a) Is this control really necessary?
If you only need one list of radio buttons, then no this control is not necessary.
If your applicaton uses many lists of radio buttons, then yes this control is necessary.
If you use a list of radio buttons in different applications, then yes this control is probably necessary.
1b) Is there a better way?
I say that deriving from a ListBox, ItemsControl, or whatever then creating styles and templates is the only way to create this control; therefore, no there is no better way.
2) Is there a professional control...
Definitely, the ListBoxEdit with the RadioListBoxEditStyleSettings.
Comments Regarding Answers
All the answers indicate that creating a RadioButtonList control is not necessary. Yet, if you need more than a couple lists of radio buttons, by the time you create the styles and control templates and maybe data template, you will end up with a collection of code artifacts that can be called a radio-button-list-control. Therefore, in my opinion, a RadioButtonList is necessary.
Moreover, my understanding is a RadioButtonList was dropped in an early WPF CTP. Which I can understand, because of the limited need for such a control that can easily be created.
Comment Regarding Accepted Answer
2) Is there a professional control...
Definitely, the ListBoxEdit with the RadioListBoxEditStyleSettings.
Lastly Comment on Mike Strobel's Answer
The RadioButtonList that I have is the end-result of his answer. While I am good at creating custom-controls, I rather let third-party component makers, such as Infragistics and DevExpress, create and support a basic control like this one.
Is this control really necessary? Is there a better way?
As #lawc points out, no, it is not necessary. It may, however, be preferable, depending on what level of flexibility you desire. A reusable style is easy enough to create, but doing it "correctly" is a bit more involved than simply setting a custom ItemTemplate.
Using Styles
An ItemsControl in WPF will wrap its items in appropriate containers. Each of the selector controls in core WPF overrides the logic which determines whether an item is capable of serving as its own container, as well as the factory code which produces new item containers. A ListBox, for example, will wrap each of its items in a ListBoxItem (unless the item itself is already a ListBoxItem). The style applied to these containers can be set for the parent ItemsControl via the ItemContainerStyle property. This differs from the ItemTemplate property, which allows you to control the appearance of the item within the container. More specifically, it overrides the content template applied to the ContentPresenter within the container.
Since a RadioButton does not derive from ListBoxItem, simply setting the ItemTemplate will produce a list of RadioButton controls embedded within ListBoxItem controls, which means they will still have the same selection chrome normally associated with ListBox controls, and possibly some layout and focus oddities. This is probably not what you want.
Instead, override the ItemContainerStyle and use it to assign a custom ListBoxItem template which embeds a RadioButton. You can probably get away with not setting the GroupName property at all, which eliminates possible name collisions. Instead, just establish a two-way binding between the RadioButton.IsChecked property and the templated parent's ListBoxItem.IsSelected property.
In order to use this technique conveniently, one generally creates a Style resource (available application-wide) which can be applied to the appropriate ListBox instances, and which sets the ItemContainerStyle. Alternatively, you can make the container style available as a global resource and set that on your ListBox instances. Either way, you need to set a property.
Using a Custom Control
While WPF evangelists often recite the philosophy of preferring custom styles over custom controls, in practice this is not always convenient. You may find it more convenient to create a RadioButtonList which extends the ListBox control, and then give it a default style which automatically applies the custom style described above. This gets you out of manually assigning the list style or container style on every ListBox instance, but it's not a huge win.
But maybe you want a bit more control over the appearance of the RadioButton items. For instance, you may want to:
Adjust the margin around the "bullet" of each RadioButton item;
Adjust the vertical alignment of the bullets relative to the content;
Support both horizontal and vertical orientations;
Automatically disable the RadioButton content for items which are not selected.
Creating your own implementation, most likely derived from ListBox, allows you to add these features easily, even after you are already using your radio list across your application. This could be done with the technique above too, though it may require an attached behavior or some attached properties, in which case you end up with a somewhat fragmented design.
Third-Party Solutions
Is there a professional control, open-source or otherwise, that will allow me to get the benefits of data-binding without the headaches?
This is not an uncommon use case, and I have no doubt there are some implementations floating around. Some may be in open source frameworks, and some may be extracted from open source applications. As for third-party implementations, I do know that Actipro ships a RadioButtonList in their Shared WPF library, which is included with all of their WPF components. When last I checked, it was not available on its own. It does, however, support all of the additional features I listed above.
I can only tell you that DevExpress uses a ListBoxEdit with a RadioListBoxEditStyleSettings to represent a group of RadioButtons. Practically it is the same as your control you are using, but i think it provides better functionality and is well tested. A RadioButton is not provided by DevExpress and in my application i use the Default RadionButton-Control provided by WPF/Silverlight.
You use the RadioListBoxEdit of DevExpress as follows:
<dxe:ListBoxEdit SelectedItem={Binding CheckItem, Mode=TwoWay}>
<dxe:ListBoxEdit.StyleSettings>
<dxe:RadioListBoxEditStyleSettings />
</dxe:ListBoxEdit.StyleSettings>
</dxe:ListBoxEdit>
More information about the ListBoxEdit of DevExpress can be found here
In my opinion you don't need this control.
You can simply use .Net ListBox to achieve all your existing functionality.
Using ListBox.ItemsSource you can data bind your options collection
Specify ListBox.ItemTemplate containing the RadioButton, in this template you can data bind your view model property to RadioButton.GroupName
IMHO, a control deriving from ItemsControl would be the cleanest approach.
Then you probably would override
IsItemItsOwnContainerOverride() with return item is RadioButton;
GetContainerForItemOverride() to return a new RadioButton() for each item and
PrepareContainerForItemOverride() to set up binding of ToggleButton.IsCheckedProperty and ContentControl.ContentProperty.
While these parts are just boilerplate code, some more efforts may lie in the implementation of the keyboard behavior.

Attached properties vs. custom control

I have often bemoaned the fact that the WPF ToggleButton does not have properties for AlternateContent and AlternateContentForeground. I'm curious if there's any advantage to creating a DependencyObject with attached properties, or deriving a custom control from ToggleButton?
My assumption is that attached properties are advantageous if they are useable on more than one control. So in my case I'm leaning towards a derived control since those properties are unique to the togglebutton.
AttachedProperties are useful in a couple scenarios:
You want to use them as attached behaviors on things that interact with another Control, like Grid.Row
You want to add properties to a control but you don't want to force clients that get that behavior to be derived from your specific type. E.g. if you had a behavior that you wanted on Buttons rather than ToggleButton, then you may want to go with that approach so you could get that new property on ToggleButton and RadioButton, rather than forcing someone to derive from MyCoolButton.
For what you're describing just subclassing ToggleButton seems to make sense.
Actually, this kind of styling should be done with a trigger, or using the VisualStateManager.

Quickest way to inherit a standard control in WPF?

I just want to wrap a standard control with some more additional properties (look stay the same, I don't want to do theming in first stage).
Can I just inherit from this standard control instead of UserControl or Control ? In fact I read it is obligatoryb to use Custom Control Project Template and not UserControl ontrol Project Template. Why ?
Update: I try with a Custom Control Project and inherit from the standard slider but I have nothing show up visually ! Now what should I do to have the same visual slider as the standard one ?
I know the difference between a user control and a custom control but in practice how do you do when you just want ONE single standard control ? How will a slider for example resize AUTOMATICALLY if I encapsulate it inside a User Control instead of a Custom Control ?
A custom control is a single control and can derive from another control, this would support styling. A UserControl is a composite control out of many different controls, and as a whole, doesn't support styling (the parts do however).
If you want to add features of any kind to an existing control, derive from it. If you want to pack several controls together to make it easier to handle them (you could still add DP's to it), use a UserControl.
A custom control alone won't do anything related to resizing etc, that is dependent on the settings you supply to it from the outside (ie. HorizontalAlignment, VerticalAlignment and others) when you used it in a container. The custom control should inherit the default template from the base class unless you override it.

Difference between Control Template and Data Template in wpf

Can someone elaborate the difference between ControlTemplate and DataTemplate in wpf?
What should one use in case of custom controls? Like for example a StackPanel which possibly has an image and a TextBox?
It seems confusing in some cases where you define a custom control using the 'Content' property.
It would be great if an example of how each can be used in different scenarios can be provided.
A ControlTemplate is used to change the look of an existing control. So if you don't want your buttons to look rectangular, you can define a control Template which makes them look oval or any irregular shape. It's a way to customize 'look-less' stock WPF controls ; an alternative to writing your own user-controls. More details
A DataTemplate is used to specify how an instance of a specific class (usually a Data Transfer object - an object with properties) is to be rendered visually. e.g. define a DataTemplate to visualize a Customer instance in a listbox displaying all customers. More details

Resources