How to Preselect in the Nested List View MAUI?

Sowndarrajan Vijayaragavan 410 Reputation points
2024-06-20T18:29:26.79+00:00

TRAIL.XAML

<?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="Bluetooth.View.Trail"
             Title="Trail">
    <StackLayout>
        <ListView x:Name="MainListview" ItemsSource="{Binding MainItems}"  VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Grid  RowDefinitions="50,Auto" RowSpacing="0" ColumnSpacing="0">
                            <!-- Main item content -->
                            <Label Grid.Row="0"  Text="{Binding MainItemName}" Margin="10,0,0,0"/>
                            <BoxView Grid.Row="1" HeightRequest="1" BackgroundColor="#14000000" Color="#14000000" 
                                     VerticalOptions="CenterAndExpand"/>
                            </Grid>
                            <ListView x:Name="SubListview" ItemsSource="{Binding SubItems}" SelectedItem="{Binding SelectedSubItem, Mode=TwoWay}" HasUnevenRows="True">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
                                            <StackLayout>
                                                <Grid  RowDefinitions="50,Auto" RowSpacing="0" ColumnSpacing="0">
                                                    <!-- Sub item content -->
                                                    <Label Grid.Row="0"  Text="{Binding SubItemName}" Margin="10,0,0,0"/>
                                                    <BoxView Grid.Row="1" HeightRequest="1" BackgroundColor="#14000000" Color="#14000000" 
                                                        VerticalOptions="CenterAndExpand"/>
                                                </Grid>
                                            </StackLayout>
                                        </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Grid ColumnDefinitions="100,100" ColumnSpacing="50" Margin="0,0,0,300">
            <Button Grid.Column="0" Text="Previous"/>
            <Button Grid.Column="1" Text="Next"/>
        </Grid>
    </StackLayout>
</ContentPage>


TRAIL.XAML.CS

using System.Collections.ObjectModel;

namespace Bluetooth.View;

public partial class Trail : ContentPage
{
	public Trail()
	{
		InitializeComponent();
        // Sample data with preselected sub-items
        var mainItems = new ObservableCollection<MainItem>
            {
                new MainItem
                {
                    MainItemName = "Main Item 1",
                    SubItems = new ObservableCollection<SubItem>
                    {
                        new SubItem { SubItemName = "Sub Item 1.1" },
                        new SubItem { SubItemName = "Sub Item 1.2" }
                    },
                    SelectedSubItem = new SubItem { SubItemName = "Sub Item 1.1" } // Preselect the first sub-item
                },
                new MainItem
                {
                    MainItemName = "Main Item 2",
                    SubItems = new ObservableCollection<SubItem>
                    {
                        new SubItem { SubItemName = "Sub Item 2.1" },
                        new SubItem { SubItemName = "Sub Item 2.2" }
                    },
                    SelectedSubItem = new SubItem { SubItemName = "Sub Item 2.2" } // Preselect the second sub-item
                }
            };

        BindingContext = new { MainItems = mainItems };
        MainListview.SelectedItem = mainItems.FirstOrDefault();  
    }




    public class MainItem
    {

        public string MainItemName { get; set; }
        public ObservableCollection<SubItem> SubItems { get; set; }
        public SubItem SelectedSubItem { get; set; }
    }

    public class SubItem
    {
        public string SubItemName { get; set; }
    }
}

User's image

I am able to preselect the first item from MainListview using below function
MainListview.SelectedItem = mainItems.FirstOrDefault();

Solution Expected:
a. SubListview.SelectedItem how to preselect the subitem.
b. At launch of the page
Main item 1 and Sub item 1.1 Has to be preselected
then after click on Next button
step 1 - Sub item 1.1 (De - Selected)
step 2 - Main item 1 and Sub item 1.2 (Selected)
Accordingly, it should select items from the list.
Help me to achieve the desired result.

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,207 questions
0 comments No comments
{count} votes

Accepted answer
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 38,906 Reputation points Microsoft Vendor
    2024-06-21T03:00:42.8133333+00:00

    Hello,

    The reason SubItem can't be preselected is because of this code.

    SelectedSubItem = new SubItem { SubItemName = "Sub Item 1.1" } // Preselect the first sub-item
    

    Passing this declaration at initialization time actually creates a new object, not the memory address corresponding to the SubItems. Therefore, in order to be able to implement the functionality of pre-selected SubItem, you need to keep the memory address consistent.

    mainItems[0].SelectedSubItem = mainItems[0].SubItems[0];
    mainItems[1].SelectedSubItem = mainItems[1].SubItems[1];
    

    In addition, for data in the Model layer, you need to implement the INotifyChanged method to enable the data to notify the view layer when it has changed.

    public class MainItem : INotifyPropertyChanged
            {
                private string _mainItemName;
                private ObservableCollection<SubItem> _subItems;
                private SubItem _selectedSubItem;
                public string MainItemName {
                    get => _mainItemName;
                    set
                    {
                        if (_mainItemName != value)
                        {
                            _mainItemName = value;
                            OnPropertyChanged(); // reports this property
                        }
                    }
                }
                public ObservableCollection<SubItem> SubItems {
                    get => _subItems;
                    set
                    {
                        if (_subItems != value)
                        {
                            _subItems = value;
                            OnPropertyChanged(); // reports this property
                        }
                    }
                }
                public SubItem SelectedSubItem {
                    get => _selectedSubItem;
                    set
                    {
                        if (_selectedSubItem != value)
                        {
                            _selectedSubItem = value;
                            OnPropertyChanged(); // reports this property
                        }
                    }
                }
     
                public event PropertyChangedEventHandler? PropertyChanged;
                public void OnPropertyChanged([CallerMemberName] string name = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
     
            public class SubItem : INotifyPropertyChanged 
            {
                private string _subItemName;
                public string SubItemName {
                    get => _subItemName;
                    set
                    {
                        if (_subItemName != value)
                        {
                            _subItemName = value;
                            OnPropertyChanged(); // reports this property
                        }
                    }
                }
                public event PropertyChangedEventHandler? PropertyChanged;
                public void OnPropertyChanged([CallerMemberName] string name = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
    

    Best Regards,

    Alec Liu.


    If the answer is the right solution, 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.


0 additional answers

Sort by: Most helpful