I'm seeing a really weird behaviour,I created a ContentView called ObservationsListView
<Grid
x:Class="NedChatApp.Custom.ObservationsListView"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:custom="clr-namespace:NedChatApp.Custom"
xmlns:modelObs="clr-namespace:NedChatApp.Models.Observations"
Padding="10"
x:DataType="custom:ObservationsListView">
<Frame Style="{StaticResource CardView}">
<VerticalStackLayout
Grid.Column="1"
Padding="10"
Spacing="10"
VerticalOptions="Center">
<Label
HorizontalOptions="Center"
Style="{StaticResource MediumLabelBold}"
Text="{Binding ClassName}" />
<CollectionView ItemsSource="{Binding Observations}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="modelObs:ObservationStudentComplete">
<custom:ObservationView
Icon="{Binding Icon}"
IsNegative="{Binding IsNegative}"
ObservationText="{Binding ObservationText}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</Frame>
</Grid>
And the cs is
public partial class ObservationsListView : Grid
{
public static readonly BindableProperty ClassNameTextProperty = BindableProperty.Create(nameof(ClassName)
, typeof(string)
, typeof(ObservationsListView)
, null
, propertyChanged: (bindable, value, newValue) => ((ObservationsListView)bindable).ClassName = (string)newValue);
public string ClassName
{
get => (string)GetValue(ClassNameTextProperty);
set => SetValue(ClassNameTextProperty, value);
}
public static readonly BindableProperty ObservationsProperty = BindableProperty.Create(nameof(Observations)
, typeof(List<ObservationStudentComplete>)
, typeof(ObservationsListView)
, new List<ObservationStudentComplete>()
, propertyChanged: (bindable, value, newValue) => ((ObservationsListView)bindable).Observations = (List<ObservationStudentComplete>)newValue);
public List<ObservationStudentComplete> Observations
{
get => (List<ObservationStudentComplete>)GetValue(ObservationsProperty);
set => SetValue(ObservationsProperty, value);
}
public ObservationsListView()
{
InitializeComponent();
}
}
I use it in a page like this
<CollectionView
x:Name="ObservationsList"
HeightRequest="{Binding ObservationsHeight}"
ItemsSource="{Binding Observations}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="modelObs:ClassObservationReactions">
<custom:ObservationsListView
Observations="{Binding Observations}"
/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Here is the model used, ClassObservationReactions
public class ClassObservationReactions
{
public long ClaseId { get; set; }
public string ClassName { get; set; }
public DateTime Date { get; set; }
public List<ObservationStudentComplete> Observations { get; set; }
}
The strange thing is that, even though ClassName is not set in the control it stills shows the correct value when running the app, so is there some sort of autobinding going on?
If I try to manually Bind the value like this
<custom:ObservationsListView
ClassName="{Binding ClassName}"
Observations="{Binding Observations}"
/>
I get this error
No property, BindableProperty, or event found for "ClassName", or mismatching type between value and property.
It's not auto-binding, if you refer to the Populate a CollectionView with data, you may find it's just the way CollectionView binds. In the ContentPage
, when you set the ItemsSource
of a CollectionView
to the Observations
, the ObservationsListView
in the DataTemplate will directly bind to the each ClassObservationReactions
instance.
So actually you don't need to create any BindableProperty
in your code behind. You just directly bind them in XAML,
<CollectionView ItemsSource="{Binding Observations}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="modelObs:ObservationStudentComplete">
<custom:ObservationView
Icon="{Binding Icon}"
IsNegative="{Binding IsNegative}"
ObservationText="{Binding ObservationText}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Please note that instead of setting x:DataType="custom:ObservationsListView"
, please set x:DataType="modelObs:ClassObservationReactions"
for the custom control.
Another is the naming convention for bindable properties.
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.
Please let me know if you have any question.