Reputation: 377
I created a .net MAUI component called SectionTitle which takes two properties: one for the background color and a string for the label.
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
x:Class="mater.Components.SectionTitle"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:c="clr-namespace:mater.Components"
x:DataType="c:SectionTitle">
<Grid ColumnDefinitions="3*,2*">
<Grid ColumnDefinitions="Auto,*">
<Border
x:Name="Bordo"
Grid.Column="0"
Padding="5,10,20,10"
Background="{Binding BGColor}"
StrokeShape="RoundRectangle 0,10,0,10">
<Label
x:Name="Lbl"
Grid.Column="0"
Text="{Binding LabelText}" />
</Border>
</Grid>
</Grid>
</ContentView>
The corresponding c# code is the following:
namespace mater.Components;
public partial class SectionTitle : ContentView
{
public static readonly BindableProperty BGColorProperty = BindableProperty.Create(
nameof(BGColor), typeof(Brush), typeof(SectionTitle), default(Brush));
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create(
nameof(LabelText), typeof(string), typeof(SectionTitle), "");
public Brush BGColor
{
get { return (Brush)GetValue(BGColorProperty); }
set { SetValue(BGColorProperty, value); }
}
public string LabelText
{
get { return (string)GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
public SectionTitle()
{
InitializeComponent();
BindingContext = this;
}
}
When using it inside a CollectionView the binding is working when using the Label property of my model directly, but it is not working when the data is passed through my SectionTitle component. Setting a static values for LabelText works.
<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
x:Class="mater.Views.HygienePage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:c="clr-namespace:mater.Components"
xmlns:local="clr-namespace:mater"
xmlns:models="clr-namespace:mater.Models"
xmlns:vm="clr-namespace:mater.ViewModels"
x:DataType="vm:HygieneViewModel">
<ScrollView>
<StackLayout Margin="0,10,0,0">
<CollectionView
Margin="20,10,20,10"
ItemsSource="{Binding Cards}"
SelectionChanged="CollectionView_SelectionChanged"
SelectionMode="Single">
<CollectionView.ItemsLayout>
<GridItemsLayout
HorizontalItemSpacing="20"
Orientation="Vertical"
Span="2"
VerticalItemSpacing="20" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:CardItem">
<StackLayout Margin="0,0,0,10" Background="{StaticResource LightGrey}">
<Grid ColumnDefinitions="Auto,*">
<Border
Grid.Column="0"
Margin="0,10,0,0"
Padding="5,10,20,10"
Background="{StaticResource Coral}"
StrokeShape="RoundRectangle 0,10,0,10">
<Label Text="{Binding Label}" />
</Border>
<Grid Grid.Column="1" />
</Grid>
<!-- Here if I put LabelText="ASD" it works, with the binding it doesn't work, the binding 3 lines before works -->
<c:SectionTitle BGColor="{StaticResource Coral}" LabelText="{Binding Label}" />
<Image HeightRequest="150" Source="{Binding Icon}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
</ContentPage>
I add also the corresponding c# code for completeness
using mater.ViewModels;
using mater.Models;
using mater.Resources.Strings;
namespace mater.Views;
public partial class HygienePage : ContentPage
{
public List<CardItem> Cards = new()
{
new CardItem
{
Icon="rischi_micro.png",
Label=AppStrings.SicRischi
},
new CardItem
{
Icon="da_evitare.png",
Label=AppStrings.SicEvitare
},
new CardItem
{
Icon="acquisto.png",
Label=AppStrings.SicLavaggio
},
new CardItem
{
Icon="cottura.png",
Label=AppStrings.SicCottura
},
new CardItem
{
Icon="contaminazioni.png",
Label=AppStrings.SicContaminazioni
},
};
public HygieneViewModel vm { get; set; }
public HygienePage()
{
InitializeComponent();
vm = new HygieneViewModel();
vm.Cards = Cards;
BindingContext = vm;
}
async void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.CurrentSelection.Count > 0)
{
CardItem selectedCard = (CardItem)e.CurrentSelection[0];
((CollectionView)sender).SelectedItem = null;
switch (selectedCard.Label)
{
case var value when value == AppStrings.SicRischi:
await Shell.Current.GoToAsync("rischimicropage");
break;
case var value when value == AppStrings.SicEvitare:
await Shell.Current.GoToAsync("evitarepage");
break;
case var value when value == AppStrings.SicLavaggio:
await Shell.Current.GoToAsync("lavaggiopage");
break;
case var value when value == AppStrings.SicCottura:
await Shell.Current.GoToAsync("cotturapage");
break;
case var value when value == AppStrings.SicContaminazioni:
await Shell.Current.GoToAsync("contaminazionipage");
break;
default:
break;
}
}
}
}
The CardItem model:
using System;
namespace mater.Models;
public class CardItem
{
public ImageSource Icon { get; set; }
public string Label { get; set; }
public bool isVisible { get; set; } = true;
}
And the viewModel:
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using mater.Models;
namespace mater.ViewModels;
public partial class HygieneViewModel: ObservableObject
{
[ObservableProperty]
private List<CardItem> cards;
}
Any idea what I am doing wrong with the binding?
Upvotes: 0
Views: 316
Reputation: 377
So as @Jason highlighted in the comments the problem was the use of BindingContext=this in the control.
I removed from the constructor in C#
BindingContext = this;
Added an x:Name to the control and the binding Source updated as follows:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
x:Class="mater.Components.SectionTitle"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:c="clr-namespace:mater.Components"
x:Name="self"
x:DataType="c:SectionTitle">
<Grid ColumnDefinitions="3*,2*">
<Grid ColumnDefinitions="Auto,*">
<Border
x:Name="Bordo"
Grid.Column="0"
Padding="5,10,20,10"
Background="{Binding Source={x:Reference self}, Path=BGColor}"
StrokeShape="RoundRectangle 0,10,0,10">
<Label
x:Name="Lbl"
Grid.Column="0"
Text="{Binding Source={x:Reference self}, Path=LabelText}" />
</Border>
</Grid>
</Grid>
</ContentView>
And now everything works correctly
Upvotes: 0