Composite controls
Composite controls are a new way of declaring controls. The main use case for composite controls is to offer an easy method of combining existing controls into larger blocks, and being able to parameterize these blocks.
Composite controls were introduced in DotVVM 4.0.
Declare the composite control
The composite control must satisfy the following two requirements:
- Inherit from the
CompositeControl
class. - Contain the static or instance method called
GetContents
. This method can have any parameters (they will be interpreted as control properties), and must return eitherDotvvmControl
orIEnumerable<DotvvmControl>
.
The declaration can look like this:
public class ImageButton : CompositeControl
{
public static DotvvmControl GetContents(
[DefaultValue("Button")] ValueOrBinding<string> text,
ICommandBinding click,
string imageUrl = "/icons/default-image.png"
)
{
return new LinkButton()
.SetProperty(b => b.Click, click)
.AppendChildren(
new HtmlGenericControl("img")
.SetAttribute("src", imageUrl),
new Literal(text)
);
}
}
Composite control properties
The code snippet above declared the ImageButton
control with 3 properties:
Text
- the property is of typeValueOrBinding<string>
. You can assign both value binding or a hard-coded value to the control. Also, the property has a default value - if it is not specified, the text "Button" will be used.Click
- the property specifiesICommandBinding
as a type, so only the command or staticCommand binding can be assigned to the property. It doesn't have a default value, therefore it is required.ImageUrl
- the property is declared asstring
, so it will support only hard-coded values in markup (or a resource binding). It has a default value.
You can also use the following types of parameters:
ITemplate
for passing templates - you can then use the TemplateHost to instantiate the template in the generated controls.DotvvmControl
orIEnumerable<DotvvmControl>
for passing child elements - you can use for example theAppendChildren
method to place the controls as children in the generated controls.IValueBinding<T>
for properties that allow only value binding expressions.
You can use nullable types - in general, they tell DotVVM that the property is optional. You can specify the default value either as a default value of the parameter, or via the [DefaultValue]
attribute. If the property is not nullable and doesn't provide a default value, it will be treated as a required property.
You can use the MarkupOptions attributes or the DataContextChange attributes on the properties, same as on the properties in markup or code-only controls.
If the property is named Content or ContentTemplate, it will be the default content property - any controls inside of the CompositeControl will be placed into this property.
See the Control properties for more information about declaring control properties.
Fluent API for building control hierarchies
In order to simplify building control hierarchy, DotVVM adds several extension methods. The most important are:
SetProperty
- can set a property to the control. It supports specifying the property via a lambda expression or by passing theDotvvmProperty
object. It also supports theValueOrBinding<T>
types, so it will internally call eitherSetValue
orSetBinding
.SetAttribute
- sets a HTML attribute. It is commonly used forHtmlGenericControl
.SetCapability
- sets a control capability property.AddCssClass
- adds a CSS class. It can be called multiple times.AppendChildren
- appends children to the control's children collection.
Using Markup controls in code-only controls
If you plan to instantiate a markup control as a child inside a composite control, you should use the MarkupControlContainer
class.
See the Markup controls page for more info.