This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Download Microsoft Edge
More info about Internet Explorer and Microsoft Edge
.NET Multi-platform App UI (.NET MAUI) bindable properties extend Common Language Runtime (CLR) property functionality by backing a property with a
BindableProperty
type, instead of with a field. The purpose of bindable properties is to provide a property system that supports data binding, styles, templates, and values set through parent-child relationships. In addition, bindable properties can provide default values, validation of property values, and callbacks that monitor property changes.
In .NET MAUI apps, properties should be implemented as bindable properties to support one or more of the following features:
Acting as a valid
target
property for data binding. For more information about target properties, see
Basic bindings
.
Setting the property through a style.
Providing a default property value that's different from the default for the type of the property.
Validating the value of the property.
Monitoring property changes.
Examples of .NET MAUI bindable properties include
Label.Text
,
Button.BorderRadius
, and
StackLayout.Orientation
. Each bindable property has a corresponding
public static readonly
field of type
BindableProperty
that is exposed on the same class and that is the identifier of the bindable property. For example, the corresponding bindable property identifier for the
Label.Text
property is
Label.TextProperty
.
Create a bindable property
The process for creating a bindable property is as follows:
Create a
BindableProperty
instance with one of the
BindableProperty.Create
method overloads.
Define property accessors for the
BindableProperty
instance.
All
BindableProperty
instances must be created on the UI thread. This means that only code that runs on the UI thread can get or set the value of a bindable property. However,
BindableProperty
instances can be accessed from other threads by marshaling to the UI thread. For more information, see
Run code on the UI thread
.
Create a property
To create a
BindableProperty
instance, the containing class must derive from the
BindableObject
class. However, the
BindableObject
class is high in the class hierarchy, so the majority of classes used for UI functionality support bindable properties.
A bindable property can be created by declaring a
public static readonly
property of type
BindableProperty
. The bindable property should be set to the returned value of one of the
BindableProperty.Create
method overloads. The declaration should be within the body of
BindableObject
derived class, but outside of any member definitions.
At a minimum, an identifier must be specified when creating a
BindableProperty
, along with the following parameters:
The name of the
BindableProperty
.
The type of the property.
The type of the owning object.
The default value for the property. This ensures that the property always returns a particular default value when it is unset, and it can be different from the default value for the type of the property. The default value will be restored when the
ClearValue
method is called on the bindable property.
Important
The naming convention for bindable properties is that the bindable property identifier must match the property name specified in the
Create
method, with "Property" appended to it.
The following code shows an example of a bindable property, with an identifier and values for the four required parameters:
public static readonly BindableProperty IsExpandedProperty =
BindableProperty.Create ("IsExpanded", typeof(bool), typeof(Expander), false);
This creates a BindableProperty instance named IsExpandedProperty
, of type bool
. The property is owned by the Expander
class, and has a default value of false
.
Optionally, when creating a BindableProperty instance, the following parameters can be specified:
The binding mode. This is used to specify the direction in which property value changes will propagate. In the default binding mode, changes will propagate from the source to the target. For more information, see Basic bindings.
A validation delegate that will be invoked when the property value is set. For more information, see Validation callbacks.
A property changed delegate that will be invoked when the property value has changed. For more information, see Detect property changes.
A property changing delegate that will be invoked when the property value will change. This delegate has the same signature as the property changed delegate.
A coerce value delegate that will be invoked when the property value has changed. For more information, see Coerce value callbacks.
A Func
that's used to initialize a default property value. For more information, see Create a default value with a Func.
Create accessors
Property accessors are required to use property syntax to access a bindable property. The Get
accessor should return the value that's contained in the corresponding bindable property. This can be achieved by calling the GetValue
method, passing in the bindable property identifier on which to get the value, and then casting the result to the required type. The Set
accessor should set the value of the corresponding bindable property. This can be achieved by calling the SetValue
method, passing in the bindable property identifier on which to set the value, and the value to set.
The following code example shows accessors for the IsExpanded
bindable property:
public bool IsExpanded
get => (bool)GetValue(IsExpandedProperty);
set => SetValue(IsExpandedProperty, value);
Consume a bindable property
Once a bindable property has been created, it can be consumed from XAML or code. In XAML, this is achieved by declaring a namespace with a prefix, with the namespace declaration indicating the CLR namespace name, and optionally, an assembly name. For more information, see XAML Namespaces.
The following code example demonstrates a XAML namespace for a custom type that contains a bindable property, which is defined within the same assembly as the application code that's referencing the custom type:
<ContentPage ... xmlns:local="clr-namespace:DataBindingDemos" ...>
</ContentPage>
The namespace declaration is used when setting the IsExpanded
bindable property, as demonstrated in the following XAML code example:
<Expander IsExpanded="true">
</Expander>
The equivalent C# code is shown in the following code example:
Expander expander = new Expander
IsExpanded = true
Advanced scenarios
When creating a BindableProperty instance, there are a number of optional parameters that can be set to enable advanced bindable property scenarios. This section explores these scenarios.
Detect property changes
A static
property-changed callback method can be registered with a bindable property by specifying the propertyChanged
parameter for the BindableProperty.Create
method. The specified callback method will be invoked when the value of the bindable property has changed.
The following code example shows how the IsExpanded
bindable property registers the OnIsExpandedChanged
method as a property-changed callback method:
public static readonly BindableProperty IsExpandedProperty =
BindableProperty.Create(nameof(IsExpanded), typeof(bool), typeof(Expander), false, propertyChanged: OnIsExpandedChanged);
static void OnIsExpandedChanged (BindableObject bindable, object oldValue, object newValue)
// Property changed implementation goes here
In the property-changed callback method, the BindableObject parameter is used to denote which instance of the owning class has reported a change, and the values of the two object
parameters represent the old and new values of the bindable property.
Validation callbacks
A static
validation callback method can be registered with a bindable property by specifying the validateValue
parameter for the BindableProperty.Create
method. The specified callback method will be invoked when the value of the bindable property is set.
The following code example shows how the Angle
bindable property registers the IsValidValue
method as a validation callback method:
public static readonly BindableProperty AngleProperty =
BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, validateValue: IsValidValue);
static bool IsValidValue(BindableObject view, object value)
double result;
double.TryParse(value.ToString(), out result);
return (result >= 0 && result <= 360);
Validation callbacks are provided with a value, and should return true
if the value is valid for the property, otherwise false
. An exception will be raised if a validation callback returns false
, which you should handle. A typical use of a validation callback method is constraining the values of integers or doubles when the bindable property is set. For example, the IsValidValue
method checks that the property value is a double
within the range 0 to 360.
Coerce value callbacks
A static
coerce value callback method can be registered with a bindable property by specifying the coerceValue
parameter for the BindableProperty.Create
method. The specified callback method will be invoked when the value of the bindable property is about to change, so that you can adjust the new value before it's applied.
Important
In addition to being triggered by the bindable property engine, you can invoke coerce-value callbacks from code. The BindableObject type has a CoerceValue
method that can be called to force a reevaluation of the value of its BindableProperty argument, by invoking its coerce value callback.
Coerce value callbacks are used to force a reevaluation of a bindable property when the value of the property is about to change. For example, a coerce value callback can be used to ensure that the value of one bindable property is not greater than the value of another bindable property.
The following code example shows how the Angle
bindable property registers the CoerceAngle
method as a coerce value callback method:
public static readonly BindableProperty AngleProperty =
BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, coerceValue: CoerceAngle);
public static readonly BindableProperty MaximumAngleProperty =
BindableProperty.Create("MaximumAngle", typeof(double), typeof(MainPage), 360.0, propertyChanged: ForceCoerceValue);
static object CoerceAngle(BindableObject bindable, object value)
MainPage page = bindable as MainPage;
double input = (double)value;
if (input > page.MaximumAngle)
input = page.MaximumAngle;
return input;
static void ForceCoerceValue(BindableObject bindable, object oldValue, object newValue)
bindable.CoerceValue(AngleProperty);
The CoerceAngle
method checks the value of the MaximumAngle
property, and if the Angle
property value is greater than it, it coerces the value to the MaximumAngle
property value. In addition, when the MaximumAngle
property changes the coerce value callback is invoked on the Angle
property by calling the CoerceValue
method.
Create a default value with a Func
A Func
can be used to initialize the default value of a bindable property, as demonstrated in the following example:
public static readonly BindableProperty DateProperty =
BindableProperty.Create ("Date", typeof(DateTime), typeof(MyPage), default(DateTime), BindingMode.TwoWay, defaultValueCreator: bindable => DateTime.Today);
The defaultValueCreator
parameter is set to a Func
that returns a DateTime
that represents today's date.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback.
Submit and view feedback for
This product