FlexLayout LeftToRight with Wrapping and selectable items?

Da'ud Vyd 21 Reputation points
2022-02-03T11:35:18.917+00:00

Hi folks,

I'd like to use FlexLayout to display the contents of an ObservableCollection<string> horizontally and wrap them. The items will be selectable (one at a time). I'm familiar with Picker, which permits binding to an ObservableCollection and tells me what the user selected. But FlexLayout appears to require manually adding items via C# (e.g. thisflexlayout.Children.Add(new...)). So if I add buttons, I would then use their Clicked or Command property instead of the way Picker uses SelectedItem. Is this the only way to proceed? Or is there a way to put a DataTemplate inside the FlexLayout somehow and use a single button tag to define how all items in the collection should be displayed and then use CommandParameter on the button to differentiate between them?

This is what I want to do, visually, but generate the buttons via data binding if possible:

<FlexLayout x:Name="layout" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" Wrap="Wrap" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
            <Button Text="Tag_1" WidthRequest="80"/>
            <Button Text="Tag_2 ...." WidthRequest="140"/>
            <Button Text="Tag_3" WidthRequest="70"/>
        </FlexLayout>
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,292 questions
0 comments No comments
{count} votes

Accepted answer
  1. JarvanZhang 23,936 Reputation points
    2022-02-04T03:07:25.577+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    For this function, try using Bindable layout which enables the layout class generate its content by binding to a collection of items.

       <FlexLayout BindableLayout.ItemsSource="{Binding DataCollection}"  
                    ...>  
           <BindableLayout.ItemTemplate>  
               <DataTemplate>  
                   ...  
               </DataTemplate>  
           </BindableLayout.ItemTemplate>  
       </FlexLayout>  
    

    Here is the related doc, you could refer to it.
    https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/bindable-layouts

    Best Regards,

    Jarvan Zhang


    If the response is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Da'ud Vyd 21 Reputation points
    2022-02-04T09:26:16.837+00:00

    As I mentioned in my comment above, my command no longer works and was working fine with buttons manually built in XAML. Previously, I had an unbound FlexLayout containing buttons like this:

    <Button x:Name="WalkButton" Text="Move" Grid.Row="3" Grid.Column="0" Command="{Binding DoAction}" CommandParameter="Walk"/>
    <Button x:Name="RunButton" Text="Talk" Grid.Row="3" Grid.Column="1" Command="{Binding DoAction}" CommandParameter="Run"/>
    etc...
    

    Now I bind to "Moves", an ObservableCollection<string>:

        <FlexLayout BindableLayout.ItemsSource="{Binding Moves}" Wrap="Wrap" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="{Binding}" Text="{Binding}" Command="{Binding DoAction}" CommandParameter="{Binding}"/>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </FlexLayout>
    

    The buttons look great (thanks!)...but...they do nothing when pressed. Upon stopping the application, the Console reports:

    [0:] Binding: 'DoAction' property not found on 'walk', target property: 'Xamarin.Forms.Button.Command'
    [0:] Binding: 'DoAction' property not found on 'walk', target property: 'Xamarin.Forms.Button.Command'
    [0:] Binding: 'DoAction' property not found on 'run', target property: 'Xamarin.Forms.Button.Command'
    [0:] Binding: 'DoAction' property not found on 'run', target property: 'Xamarin.Forms.Button.Command'
    [0:] Binding: 'DoAction' property not found on 'climb', target property: 'Xamarin.Forms.Button.Command'
    [0:] Binding: 'DoAction' property not found on 'climb', target property: 'Xamarin.Forms.Button.Command'
    

    I expected this to work without modifying DoAction in my ViewModel because CommandParameter="{Binding}" should send "walk", "run", etc as an argument just like before. Weird that each Binding error is reported twice, right? Also, my can execute code stopped working:

    void RefreshCanExecutes()
            {
                (DoAction as Command).ChangeCanExecute();
            }
    

    I really do like the BindableLayout.ItemsSource approach so I want to modify my code accordingly. But, I don't understand how adding a binding to the FlexLayout could have caused the C# code to stop working. (and if that really can't be the reason...well I have some real digging to do!)