0

I'm trying to add UI elements, written in C# code, to not copy and paste them multiple times in XAML file. I'm using BindableLayout in my XAML file. The problem is that I'm not seeing any element added to that BindableLayout (they're not showing at the screen when I run the app).
.NET MAUI version of this solution is 9.0.

Here is my code - XAML file:

<?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="Maui_testy.BindingLayoutTest"
    Title="BindingLayoutTest">

    <FlexLayout
        BindableLayout.ItemsSource="{Binding Letters}">
        <BindableLayout.ItemTemplate>
            <DataTemplate>
                <Button
                    Text="{Binding .}"
                />
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </FlexLayout>
</ContentPage>

C# file:

using System.ComponentModel;
using System.Diagnostics;

namespace Maui_testy;

public partial class BindingLayoutTest : ContentPage, INotifyPropertyChanged
{
    private List<char> letters;
    public List <char> Letters
    {
        get => letters;
        set
        {
            letters = value;
            OnPropertyChanged();
        }
    }

    public BindingLayoutTest()
    {
        InitializeComponent();
        BindingContext = this;
        this.letters = new List <char>();
        for(Int16 i = 65; i < 91; ++ i)
        {
            Letters.Add((char)i);
        }
    }
}
2
  • 5
    Your Letters list is not observable. Either you need to initialize Letters before InitializeComponent() gets called and BindingContext gets set (which is discouraged because it fosters bad design) or you need to make Letters observable, e.g. by using an ObservableCollection<T> instead of a List<T>. Commented Dec 2 at 8:21
  • At this point, there is no way to tell if your "contents" have any "ActualHeight". You need to specify it; or "investigate it" (in debug mode). And you might have better luck with "strings" starting out. The only time one uses single chars in a UI (usually), is for a FontIcon; otherwise it's a "character string"; which allows for unicode. Commented Dec 2 at 18:23

2 Answers 2

0

To enable binding in MAUI, your class needs to inherit from an observable type, which allows it to listen for property-change notifications. You should also define both the ItemsSource for when data is available and an empty data template for when no data is present. Additionally, ensure that all required services are properly registered in your Startup.cs or Program.cs file so they can be accessed from both your XAML and C# code.

I will advice you read more about MVVM paradigm and how MAUI approach this. https://learn.microsoft.com/en-us/dotnet/maui/xaml/fundamentals/mvvm?view=net-maui-10.0

Sign up to request clarification or add additional context in comments.

Comments

-1

Simple answer:
Change this

private List<char> letters;

to

private List<char> letters = new List<char>();

then transform this this:

this.letters = new List <char>();
        for(Int16 i = 65; i < 91; ++ i)
        {
            Letters.Add((char)i);
        }

to this:

var m = new List<char>();
for(Int16 i = 65; i < 91; ++ i)
            m.Add((char)i);
Letters = new List<char>(m);

And if this does nothing try specifying datatypes, change this:

<DataTemplate>

to this:

<DataTemplate x:DataType="x:Char">

and this:

<ContentPage 
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Maui_testy.BindingLayoutTest"
    Title="BindingLayoutTest">

to this:

<ContentPage 
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Maui_testy.BindingLayoutTest"
    xmlns:local="clr-namespace:Maui_testy"
    x:DataType="local:BindingLayoutTest"
    Title="BindingLayoutTest">

3 Comments

Your solution is not correct. The code from OP first is running InitializeComponent(); which is resolving {Binding Letters}, but in that execution point, Letters is null, so no items are displayed. Right after that, OP code is initializing Letters, but, since it's a List, changes are not updated to the UI (List is not implementing INotifyCollectionChanged and INotifyPropertyChanged). Specifying DataType in DataTemplate won't help, since is only making binding resolve faster (compiled bindings) but that is not the issue. @Julian comment is the correct answer to OP
You are partially correct, I have updated my reply to make it work. Now what is different: first of all without specifying datatypes you may see result in debug mode and nothing will happen in release, since in some cases datatypes must be specified when they are not obvious to the compiler. According to List not implementing PropertyChanged: as you can see in the original OnPropertyChanged is called every time we set new variable to the Letters, thus removing this necessity for the fixed List, such as one that was presented. What I was wrong about is adding items to it AFTER assignmen
The DataType behaviour you are describing is indeed happening when using NativeAOT apps. OP doesn't give information of that part so it's positive you brought that up. In my first comment I was just pointing out your DataType suggestion wouldn't help OP since the most obvious problem was the Binding resolving to an empty List. Your edited code might work but it's far from good practices IMHO since it's completely ignoring the whole concept of Observer pattern. You should not be worried about initializing your stuff in a specific execution point for your Binding to resolve properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.