How to bind the ItemsSource of a TemplatedPicker?

1 Answer 268 Views
TemplatedPicker
Rolf
Top achievements
Rank 1
Iron
Iron
Iron
Rolf asked on 06 Oct 2023, 06:54 PM

I have a ContentView with a bindableproperty of type IEnumerable. When I bind the property to the ItemsSource of a CollectionView it works. Then I added the CollectionView to the SelectorTemplate of a TemplatedPicker with the same binding syntax it doesn't work. What is the correct binding syntax for the ItemsSource of a CollectionView inside a TemplatedPicker?

Here the code:

ColorPicker.xaml (with CollectionView only)

    <CollectionView
        ItemsSource="{Binding Source={x:Reference this}, Path=ViewColorList}"
        HeightRequest="320"
        SelectionMode="Single">
        <CollectionView.ItemTemplate>
             <DataTemplate x:DataType="model:ColorData">
                    <Grid HeightRequest="70" WidthRequest="100" RowDefinitions="Auto, Auto">
                      <telerik:RadBorder Grid.Row="0" WidthRequest="40"
                           HeightRequest="40"
                           CornerRadius="20"
                           HorizontalOptions="Center"
                          VerticalOptions="Center"
                          BorderColor="{Binding ColorValue, Converter = {StaticResource ColorConverter}}"
                          BorderThickness="2"
                          BackgroundColor="{Binding ColorValue, Converter = {StaticResource ColorConverter}}" />
                          <Label Grid.Row="1" Text="{Binding Name}" FontSize="12" TextColor="Black" HorizontalOptions="Center"/>
                  </Grid>
          </DataTemplate>
      </CollectionView.ItemTemplate>

      <CollectionView.ItemsLayout>
        <GridItemsLayout Orientation="Vertical" Span="4" />
    </CollectionView.ItemsLayout>
</C ollectionView>

 

ColorPicker.xaml (with TemplatedPicker)

 <telerik:RadTemplatedPicker x:Name="picker"
      Placeholder="Select a Color">
      <telerik:RadTemplatedPicker.DisplayTemplate>
          <ControlTemplate>
              <Grid ColumnDefinitions="Auto, *">
                  <Grid.GestureRecognizers>
                      <TapGestureRecognizer Command="{TemplateBinding ToggleCommand}" />
                  </Grid.GestureRecognizers>
                  <telerik:RadBorder
                     Grid.Column="0"
                     WidthRequest="20"
                     HeightRequest="20"
                     CornerRadius="10"
                     VerticalOptions="Center"
                     BorderColor="{Binding Source={x:Reference ColorPicker}, Path=ViewSelectedColor.ColorValue, Converter = {StaticResource TransparentConverter}}"
                     BorderThickness="1"
                     BackgroundColor="{Binding Source={x:Reference ColorPicker}, Path=ViewSelectedColor.ColorValue, Converter = {StaticResource ColorConverter}}"/>
                  <Label Grid.Column="1" Text="{Binding Source={x:Reference ColorPicker}, Path=ViewSelectedColor.Name}" FontSize="15" TextColor="Black" Margin="12, 0, 0, 0"/>
              </Grid>
          </ControlTemplate>
      </telerik:RadTemplatedPicker.DisplayTemplate>
      <telerik:RadTemplatedPicker.SelectorTemplate>
          <ControlTemplate>
              <CollectionView
                  ItemsSource="{Binding Source={x:Reference this}, Path=ViewColorList}"
                  HeightRequest="320"
                  SelectionMode="Single">
                  <CollectionView.ItemTemplate>
                  <DataTemplate x:DataType="model:ColorData">
                <Grid HeightRequest="70" WidthRequest="100" RowDefinitions="Auto, Auto">
               <Grid.GestureRecognizers>
                   <TapGestureRecognizer Tapped="Close_ColorSelection" />
               </Grid.GestureRecognizers>
               <telerik:RadBorder Grid.Row="0" WidthRequest="40"
                   HeightRequest="40"
                   CornerRadius="20"
                   HorizontalOptions="Center"
                   VerticalOptions="Center"
                   BorderColor="{Binding ColorValue, Converter = {StaticResource ColorConverter}}"
                   BorderThickness="2"
                   BackgroundColor="{Binding ColorValue, Converter = {StaticResource ColorConverter}}" />
               <Label Grid.Row="1" Text="{Binding Name}" FontSize="12" TextColor="Black" HorizontalOptions="Center"/>
           </Grid>
       </DataTemplate>
   </CollectionView.ItemTemplate>
  
   <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Vertical" Span="4" />
   </CollectionView.ItemsLayout>
       </CollectionView>
          </ControlTemplate>
      </telerik:RadTemplatedPicker.SelectorTemplate>
  </telerik:RadTemplatedPicker>

 

ColorPicker.xaml.cs

public partial class ColorPicker : ContentView
{

    public ColorPicker()
    {
        InitializeComponent();
    }

    #region ViewColorList property
    public static readonly BindableProperty ViewColorListProperty = BindableProperty.Create(
        nameof(ViewColorList),
        typeof(IEnumerable<ColorData>),
        typeof(ColorPicker3),
        default(IEnumerable<ColorData>),
        propertyChanged: OnItemsSourcePropertyChanged);

    public IEnumerable<ColorData> ViewColorList
    {
        get => (IEnumerable<ColorData>)GetValue(ViewColorListProperty);
        set => SetValue(ViewColorListProperty, value);
    }
    #endregion
}

ColorData.cs (Model of ColorData)

public class ColorData
{

    public string Name { get; set; }
    public string ColorValue { get; set; }
}

 

 

1 Answer, 1 is accepted

Sort by
0
Accepted
Lance | Senior Manager Technical Support
Telerik team
answered on 10 Oct 2023, 04:54 PM

Hi Rolf,

Thanks for sharing the code. Although I cannot debug your issue with it, I think I can still get you pointed in the right direction.

You're using a 'this' x:Reference in your binding, but you're assuming the SelectorTemplate is in the same context that the CollectionView was by itself ('this' is relative, it is different depending on where that reference is invoked). In your first attempt 'this' is the ContentView... while in the 2nd attempt, 'this' is going to be the TemplatedPicker.

You can always test your assumptions about any binding by using a temporary converter, so that you can directly inspect the data being passed to the binding.

ItemsSource="{Binding Source={x:Reference this}, Converter={StaticResource MyDebugConverter}}"

and in the converter you're just returning the same value, but you have the opportunity to place a breakpoint

public class MyDebugConverter : IValueConverter
{
    pubic convert(....)
    {
        // put a breakpoint here and inspect the data. Is this object exactly what you're expecting?
        return value;
    }
}

This will help you validate that #1 - the binding is even happening and #2 the x:Reference is what you think it is.

Establishing a Consistent Reference

My recommendation would to eliminate unknowns and establish a reliable source of truth. by having the custom control's ContentView referenced with a name. This would avoid mishaps when using relative sources like 'this' can cause.

Step 1 - Give the custom control an x:Name

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyProject.CustomControls.ColorPicker"
             x:Name="ThisView">
...
</ContentView>

Step 2 - Now use the x:Name for the x:Reference.

ItemsSource="{Binding Source={x:Reference ThisView}, Path=ViewColorList}"

Let me know how it goes.

Please note that although you did share some helpful and relevant code, it is not enough to build a test project with, as there are a couple key missing pieces. My advice is based on an educated guess and not through using runtime diagnostics. If you would like a more definitive answer, please open a Support Ticket instead of a public forum post and share the project in private.

Regards,
Lance | Manager Technical Support
Progress Telerik

A brand new .NET MAUI course was just added to the Virtual Classroom. The training course is developed to help you get started with the Telerik UI for .NET MAUI components and features. It aims to put you in the shoes of an engineer who adds new features to an existing application. You can check it out at https://learn.telerik.com
Rolf
Top achievements
Rank 1
Iron
Iron
Iron
commented on 11 Oct 2023, 03:03 PM

Hi Lance,

 

thx, it works.

I'm looking for a good tutorial for (MAUI) XAML binding.

Lance | Senior Manager Technical Support
Telerik team
commented on 11 Oct 2023, 04:26 PM

That's great news! To be fair, this is a tricky data binding situation, and is not commonly experienced because it's very specific to building a custom control and understanding the difference in BindingContext depending on the parent's scope... so even a tutorial wouldn't have covered it unless it was explicitly about custom controls and templated views.

That being said, Microsoft has some really nice tutorials that take you through many topics and data binding is one. Here are some links I found for you to review:

 

Tags
TemplatedPicker
Asked by
Rolf
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Lance | Senior Manager Technical Support
Telerik team
Share this question
or