Skip to content
Home » Basics of .NET MAUI – Part 6 – Properties in XAML

Basics of .NET MAUI – Part 6 – Properties in XAML

Spread the love

Throughout the series we’ve been using properties a lot, practically all XAML objects had one or more properties set. In this part of the series we’ll have a look at properties in .NET MAUI in more detail. In particular, we’ll clarify terms like property elements, content properties and attached properties. But first, let’s recap on what we already know about properties.

The source code for this article is available on Github.

Property Attributes

Most of the XAML objects so far had some properties set. Here’s a Label with a couple properties:

<Label 
    Text="File"
    TextColor="Firebrick"
    FontSize="20" />

Text, TextColor and FontSize are so-called property attributes, because these are attributes that we use to set the properties of an object. So here we have a Label object with three properties set. This is how we’ve been using properties in XAML so far and this is how we usually use them if they are set to a simple value like a string or integer. If we must set them to a more complex value, like another object for example, this syntax isn’t very useful. Instead we should use so-called property elements. Actually, we can use property elements as an alternative to property attributes even for simple types, which will make the code a little more verbose, but it’s up to you which syntax you choose. Let’s have a look at property elements then.

Property Elements

As I just said, property elements can be used instead of property attributes even if we want to set them to simple values. Let’s change all the property attributes in the example above to property elements:

<Label>
    <Label.Text>
        File
    </Label.Text>
    <Label.TextColor>
        Firebrick
    </Label.TextColor>
    <Label.FontSize>
        20
    </Label.FontSize>
</Label>

So, the value of each property is placed between the property element’s opening and closing tags and it constitutes its content.

You can also mix and match:

<Label
    Text="File"
    TextColor="Firebrick">            
    <Label.FontSize>
        20
    </Label.FontSize>
</Label>

Generally, you will usually use property attributes for simple values like that. But sometimes it’s not so easy. This is the case if the value of the property is too complex to be written as a string. You saw an example in the previous part of the series where we were discussing the Grid layout. The Grid has the RowDefinitions and ColumnDefinitions properties. These are collections of RowDefinition and ColumnDefinition objects respectively. Here’s how we use the property element syntax to set these two properties:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="3*" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="200"/>
    </Grid.ColumnDefinitions>        
</Grid>

You may also remember that in this particular case we can also use property attributes to simplify the code:

<Grid
    RowDefinitions="50, 3*, Auto, *"
    ColumnDefinitions="*, Auto, 200">>   
</Grid>

But it’s not always possible. We’ll be using property elements a lot throughout this series.

Attached Properties

Our next topic is attached properties. I’ve used this term several times so far. These are properties that are defined in one class and attached to objects of another class. Have a look at the following definition of a Grid and its children, similar to the one from the previous part of the series, here abbreviated to include just the attached properties:

<Grid>
    ...
    <BoxView 
        Grid.Row="1"
        Grid.Column="1" />
    <BoxView 
        Grid.Row="1"
        Grid.Column="2"
        Grid.RowSpan="2"
        Grid.ColumnSpan="3" />
</Grid>

Here, Grid.Row, Grid.Column, Grid.RowSpan and Grid.ColumnSpan are properties of the Grid class, but they are set on the children of the Grid.

You saw another example of attached properties when we were talking about the AbsoluteLayout. Have a look at the code again:

...
    <AbsoluteLayout Margin="40" BackgroundColor="Beige">
        <BoxView 
            Color="Green"
            AbsoluteLayout.LayoutBounds=".5, .5, 200, 200" 
            AbsoluteLayout.LayoutFlags="PositionProportional"/>
        <BoxView 
            Color="Red"
            AbsoluteLayout.LayoutBounds="100, 400, .2, .1"
            AbsoluteLayout.LayoutFlags="SizeProportional" />
        <BoxView 
            Color="Blue"
            AbsoluteLayout.LayoutBounds="1, 1, .25, .5"
            AbsoluteLayout.LayoutFlags="PositionProportional,SizeProportional" />
    </AbsoluteLayout>
</ContentPage>

Can you spot the attached properties right away? I’m sure you can. Here AbsoluteLayout.LayoutBounds and AbsoluteLayout.LayoutFlags are properties of the AbsoluteLayout class, but they are set on the BoxView objects.

Content Properties

Finally, there’s one more term worth mentioning as far as properties in XAML are concerned, content properties.

Let’s define a simple label:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Slugrace.TestPage"
             Title="TestPage">
    <VerticalStackLayout>
        <Label
            TextColor="Firebrick"
            FontSize="100"
            Text="Hey there">            
        </Label>
    </VerticalStackLayout>
</ContentPage>

We could use the property element syntax as well. Let’s use it for the Text property:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Slugrace.TestPage"
             Title="TestPage">
    <VerticalStackLayout>
        <Label
            TextColor="Firebrick"
            FontSize="100">
            <Label.Text>
                Hey there
            </Label.Text>
        </Label>
    </VerticalStackLayout>
</ContentPage>

If you run the code, you will see this:

We set three properties on the Label: TextColor, FontSize and Text. In case of the Label class, the Text property has a special status. It’s a so-called content property. Each class defines its own content property, it doesn’t have to be Text, but in case of Label it’s Text. A content property is a property that is not required in XAML. Anything that appears between the opening and closing tags of the object is assigned to that property. So, we could place the string “Hey there” directly between the tags of Label:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Slugrace.TestPage"
             Title="TestPage">
    <VerticalStackLayout>
        <Label
            TextColor="Firebrick"
            FontSize="100">
            Hey there
        </Label>
    </VerticalStackLayout>
</ContentPage>

And it still works the same. But how do you know which property is the content property of a given class? Right-click on the Label object in Visual Studio and select Go To Definition:

You will see the definition of the Label class. Here’s the first part of it:

[ContentProperty("Text")]
    public class Label : View, ILabel, IView, IElement, ...

As you can see, the class is decorated with the ContentProperty attribute with the name of the content property passed to it.

Actually, there are more objects defined in our code snippet above. There’s also ContentPage and VerticalStackLayout. What are their content properties? Let’s check it out. Right-click on the ContentPage object and select Go To Definition. As you can see, Content is the content property:

[ContentProperty("Content")]
    public class ContentPage : TemplatedPage, IContentView, IView, ...

And you can’t see the Content property in the XAML code. This is exactly because it’s the content property, which can be omitted. If so, anything between the opening and closing tags of ContentPage is its content. But we can still use it, if we want to, like so:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Slugrace.TestPage"
             Title="TestPage">
    <ContentPage.Content>
        <VerticalStackLayout>
            <Label
                TextColor="Firebrick"
                FontSize="100">
                Hey there
            </Label>
        </VerticalStackLayout>
    </ContentPage.Content>    
</ContentPage>

What about VerticalStackLayout? It turns out, its content property is Children:

[ContentProperty("Children")]
    public class VerticalStackLayout : StackBase
    ...

So, let’s add the content property explicitly to the code as well:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Slugrace.TestPage"
             Title="TestPage">
    <ContentPage.Content>
        <VerticalStackLayout>
            <VerticalStackLayout.Children>
                <Label
                    TextColor="Firebrick"
                    FontSize="100">
                    Hey there
                </Label>
            </VerticalStackLayout.Children>            
        </VerticalStackLayout>
    </ContentPage.Content>    
</ContentPage>

And remember, there’s only one content property for each class.

Good, I think some of the XAML terminology has been clarified, so let’s take a break from XAML for a while. As you know, you can write all your code in C#. In the next part of the series we’ll see how to create objects and properties in C#.


Spread the love

Leave a Reply