Reputation: 323
I'm using .NET MAUI and trying to create a set of checkbox lists that will be put inside a FlexLayout so that they will wrap. When I hard code the data, it works fine. Here's the working hard-coded solution:
<FlexLayout
Grid.Row="5"
Grid.Column="0"
Grid.ColumnSpan="2"
Direction="Row"
Wrap="Wrap">
<VerticalStackLayout HeightRequest="200" WidthRequest="200">
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 1-1" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 1-2" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 1-3" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 1-4" />
</HorizontalStackLayout>
</VerticalStackLayout>
<VerticalStackLayout HeightRequest="200" WidthRequest="200">
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 2-1" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 2-2" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 2-3" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 2-4" />
</HorizontalStackLayout>
</VerticalStackLayout>
<VerticalStackLayout HeightRequest="200" WidthRequest="200">
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 3-1" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 3-2" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 3-3" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 3-4" />
</HorizontalStackLayout>
</VerticalStackLayout>
<VerticalStackLayout HeightRequest="200" WidthRequest="200">
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 4-1" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 4-2" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 4-3" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<CheckBox IsChecked="False" />
<Label Margin="5,15,0,0" Text="Label 4-4" />
</HorizontalStackLayout>
</VerticalStackLayout>
</FlexLayout>
and the results, with a bit of wrapping looks like the following:
I tried using the CollectionView grouping feature, but the one issue I would always run into was that the GroupedCheckboxLists ( the extension of the list) would cause my XAML error that the IsChecked and Label attributes were not found. I tried all the solutions and never got it to work.
So now I'm trying nested CollectionViews and I can get results, but it shows all the checkboxes vertically and not side-by-side. Here's my View Model:
public partial class CheckBoxViewModel : ObservableObject
{
[ObservableProperty]
string id;
[ObservableProperty]
string label;
[ObservableProperty]
bool isChecked;
[ObservableProperty]
int groupNumber;
[ObservableProperty]
int sortOrder;
}
public partial class CheckBoxGroupViewModel : ObservableObject
{
[ObservableProperty]
string group;
[ObservableProperty]
List<CheckBoxViewModel> checkBoxes;
public CheckBoxGroupViewModel(string name, List<CheckBoxViewModel> checkBoxes)
{
this.group = name;
this.checkBoxes = checkBoxes;
}
}
and here's my XAML:
<FlexLayout
Grid.Row="5"
Grid.Column="0"
Grid.ColumnSpan="2"
Direction="Row"
Wrap="Wrap">
<CollectionView HorizontalOptions="FillAndExpand" ItemsSource="{Binding ProjectRooms}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="vm:Common.CheckBoxGroupViewModel">
<VerticalStackLayout HeightRequest="200" WidthRequest="200">
<CollectionView ItemsSource="{Binding CheckBoxes}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="vm:Common.CheckBoxViewModel">
<HorizontalStackLayout>
<CheckBox IsChecked="{Binding IsChecked}" />
<Label Margin="5,15,0,0" Text="{Binding Label}" />
</HorizontalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</FlexLayout>
This shows like the following:
Any Ideas how to get it to show the groups side-by-side and wrap?
UPDATE:
I'm trying the solution below but the problem is that I want these to be in a FlexLayout so that it'll fit on any device, and wrap the Checkboxes within their Group. Here's the update to a FlexLayout, but still getting all the VerticalLayouts in one column:
<FlexLayout
Grid.Row="5"
Grid.Column="0"
Grid.ColumnSpan="2"
Direction="Row"
Wrap="Wrap">
<CollectionView HorizontalOptions="FillAndExpand" ItemsSource="{Binding ProjectRooms}">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout
BindableLayout.ItemsSource="{Binding CheckBoxes}"
HeightRequest="200"
WidthRequest="200">
<BindableLayout.ItemTemplate>
<DataTemplate>
<HorizontalStackLayout>
<CheckBox IsChecked="{Binding IsChecked}" />
<Label Margin="5,15,0,0" Text="{Binding Label}" />
</HorizontalStackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</FlexLayout>
Upvotes: 1
Views: 712
Reputation: 13879
You can try to put BindableLayout
inside of CollectionView
to achieve this.
Based on your code, I created a demo and achieved this fucntion.
You can refer to the following code:
<?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="MauiInnerListApp0201.MainPage"
xmlns:vm="clr-namespace:MauiInnerListApp0201.Models" >
<ContentPage.BindingContext>
<vm:TestViewModel></vm:TestViewModel>
</ContentPage.BindingContext>
<CollectionView ItemsSource="{Binding Groups}"
ItemsLayout="VerticalGrid, 3">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout>
<Label Text="{Binding Group}" />
<StackLayout BindableLayout.ItemsSource="{Binding CheckBoxes}" Orientation="Vertical">
<BindableLayout.ItemTemplate>
<DataTemplate>
<HorizontalStackLayout>
<CheckBox IsChecked="{Binding IsChecked}" />
<Label Margin="5,15,0,0" Text="{Binding Label}" />
</HorizontalStackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
TestViewModel.cs
public class TestViewModel
{
public List<CheckBoxGroupViewModel> Groups { get; set; } = new List<CheckBoxGroupViewModel>();
public TestViewModel()
{
List<CheckBoxViewModel> Items1 = new List<CheckBoxViewModel>();
CheckBoxGroupViewModel group1;
Items1.Add (new CheckBoxViewModel() { GroupNumber = 1 , IsChecked= true, Id= "1", Label= "Label 1-1", SortOrder = 01});
Items1.Add (new CheckBoxViewModel() { GroupNumber = 1 , IsChecked= true, Id= "2", Label= "Label 1-1", SortOrder = 01});
Items1.Add (new CheckBoxViewModel() { GroupNumber = 1 , IsChecked= false, Id= "3", Label= "Label 1-1", SortOrder = 01});
Items1.Add (new CheckBoxViewModel() { GroupNumber = 1 , IsChecked= true, Id= "4", Label= "Label 1-1", SortOrder = 01});
group1 = new CheckBoxGroupViewModel("group-1", Items1);
List<CheckBoxViewModel> Items2 = new List<CheckBoxViewModel>();
CheckBoxGroupViewModel group2;
Items2.Add(new CheckBoxViewModel() { GroupNumber = 2, IsChecked = true, Id = "1", Label = "Label 2-1", SortOrder = 01 });
Items2.Add(new CheckBoxViewModel() { GroupNumber = 2, IsChecked = true, Id = "2", Label = "Label 2-1", SortOrder = 01 });
Items2.Add(new CheckBoxViewModel() { GroupNumber = 2, IsChecked = false, Id = "3", Label = "Label 2-1", SortOrder = 01 });
Items2.Add(new CheckBoxViewModel() { GroupNumber = 2, IsChecked = true, Id = "4", Label = "Label 2-1", SortOrder = 01 });
group2 = new CheckBoxGroupViewModel("group-2", Items2);
List<CheckBoxViewModel> Items3 = new List<CheckBoxViewModel>();
CheckBoxGroupViewModel group3;
Items3.Add(new CheckBoxViewModel() { GroupNumber = 3, IsChecked = true, Id = "1", Label = "Label 3-1", SortOrder = 01 });
Items3.Add(new CheckBoxViewModel() { GroupNumber = 3, IsChecked = true, Id = "2", Label = "Label 3-1", SortOrder = 01 });
Items3.Add(new CheckBoxViewModel() { GroupNumber = 3, IsChecked = false, Id = "3", Label = "Label 3-1", SortOrder = 01 });
Items3.Add(new CheckBoxViewModel() { GroupNumber = 3, IsChecked = true, Id = "4", Label = "Label 3-1", SortOrder = 01 });
group3 = new CheckBoxGroupViewModel("group-3", Items3);
Groups.Add(group1);
Groups.Add(group2);
Groups.Add(group3);
}
}
Note:
You can adjust the column number by ItemsLayout="VerticalGrid, 3"
.
For more information, you can check: Specify CollectionView layout.
Update:
So the main issue is that I want these Checkbox Groups in a FlexLayout as I do not know how many will actually be in the list and it'll be shown on different devices. I'd rather not set it to static 3 columns.
Please try the following code:
<FlexLayout
BindableLayout.ItemsSource="{Binding Groups}" Direction="Row" AlignContent="Start" AlignItems="Start"
VerticalOptions="StartAndExpand" JustifyContent="Start"
Wrap="Wrap">
<BindableLayout.ItemTemplate>
<DataTemplate>
<VerticalStackLayout
BindableLayout.ItemsSource="{Binding CheckBoxes}" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<HorizontalStackLayout>
<CheckBox IsChecked="{Binding IsChecked}" />
<Label Margin="5,15,0,0" Text="{Binding Label}" />
</HorizontalStackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>
Upvotes: 2