net maui how to create bindable layout with selected item color change ?

Sami 966 Reputation points
2024-02-12T22:26:31.13+00:00

net maui 2 menus how to create bindable layout with selected item colors change by view model ? and clear all selected item when another menu ( collectionview has bug about removing selected items clearing )

windows platform

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
4,033 questions
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 81,016 Reputation points Microsoft External Staff
    2024-02-14T01:57:20.4333333+00:00

    Hello,

    No need to do it by creating bindable layout with selected item color. Firstly, please add INotifyPropertyChanged Interface for your MenuItem, after that, your categoryColor and selected status will be changed at the runtime. And I add Selected property to identify the item selected or not.

    public class MenuItem:INotifyPropertyChanged
    {
        public string? Title { get; set; }
        public string? Icon { get; set; }
      
    
    
       private string categoryColor;
    
    
       public string CategoryColor
        {
            get { return categoryColor; }
            set { categoryColor = value; OnPropertyChanged(); }
        }
    
    
       private bool selected;
    
    
       public bool Selected
        {
            get { return selected; }
            set {
                selected = value;
                OnPropertyChanged();
            }
        }
    
     public event PropertyChangedEventHandler? PropertyChanged;
    
    
       public void OnPropertyChanged([CallerMemberName] string name = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
    

    Then I add two Command when you tab the Label. If you click the left menu, item seleted status will be setted to false and set the background to white. By default, I set the CategoryColor to white.

    
    public class MenuViewModel
    {
    
    
       public ICommand MyLeftSLTapCommand { get; set; }
        public ICommand MyRightSLTapCommand { get; set; }
    
    
       public MenuViewModel()
        {
            PopulateData();
            MyLeftSLTapCommand = new Command(e =>
            {
                foreach (MenuItem item in MenuRight) {
                    item.Selected = false;
                    item.CategoryColor = "#FFFFFF";
                }
                
                
                MenuItem menuItem = e as MenuItem;
                menuItem.Selected = !menuItem.Selected;
    
    
               if (menuItem.Selected && menuItem.Title.Equals("Food"))
                {
                    menuItem.CategoryColor = "#FF0000";
                }
                else if (menuItem.Selected && menuItem.Title.Equals("Organic"))
                {
                    menuItem.CategoryColor = "#339933";
                }
                else
                {
                    menuItem.CategoryColor = "#FFFFFF";
                }
            });
    
    
            MyRightSLTapCommand = new Command(e =>
            {
                foreach (MenuItem item in MenuLeft)
                {
                    item.Selected = false;
                    item.CategoryColor = "#FFFFFF";
                }
    
    
               MenuItem menuItem = e as MenuItem;
                menuItem.Selected = !menuItem.Selected;
    
    
               if (menuItem.Selected && menuItem.Title.Equals("My Account"))
                {
                    menuItem.CategoryColor = "#FF4500";
                }
                else if (menuItem.Selected && menuItem.Title.Equals("My Messages"))
                {
                    menuItem.CategoryColor = "#C19434";
                }
                else
                {
                    menuItem.CategoryColor = "#FFFFFF";
                }
            });
        }
    
    
       public ObservableCollection<MenuItem> _MenuRight = new ObservableCollection<MenuItem>();
        public ObservableCollection<MenuItem> MenuRight
        {
            get
            {
                return _MenuRight;
            }
            set
            {
                _MenuRight = value;
    
    
               // OnPropertyChanged("MenuRight");
            }
        }
    
    
       void PopulateData()
        {
            MenuLeft.Clear();
            MenuLeft.Add(new MenuItem() { Title = "Food", CategoryColor = "#FFFFFF", Icon = "\xe84a", Selected=false});
            MenuLeft.Add(new MenuItem() { Title = "Organic", CategoryColor = "#FFFFFF", Icon = "\x3c", Selected = false });
            MenuRight.Clear();
            MenuRight.Add(new MenuItem() { Title = "My Account", CategoryColor = "#FFFFFF", Icon = "\xe84a", Selected = false });
            MenuRight.Add(new MenuItem() { Title = "My Messages", CategoryColor = "#FFFFFF", Icon = "\x3c" , Selected = false });
        }
        public ObservableCollection<MenuItem> _MenuLeft = new ObservableCollection<MenuItem>();
        public ObservableCollection<MenuItem> MenuLeft
        {
            get
            {
                return _MenuLeft;
            }
            set
            {
                _MenuLeft = value;
            }
        }
    }
    

    In the end. I add following layout with two menus. And I bind the CategoryColor to the Label's BackgroundColor.

    I add tabCommand for Label. When label clicked, tabCommand will be executed, this label's backgroundcolor will be changed.

    <ContentPage 
    ...
                 xmlns:local="clr-namespace:MauiYourProject"
    ...
                 >
     <ScrollView VerticalOptions="FillAndExpand" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never">
           <HorizontalStackLayout>
               <StackLayout BindableLayout.ItemsSource="{Binding MenuLeft}" Orientation="Vertical" x:Name="MyLeftSL">
    
    
                  <BindableLayout.ItemTemplate>
    
    
                      <DataTemplate>
    
    
                          <ContentView >
    
    
                              <Border StrokeThickness="0" WidthRequest="60"  HorizontalOptions="FillAndExpand" >
                                   <Grid>
                                       <Label  TextColor="{DynamicResource SecondaryTextColor}"  Text="{Binding Icon}" BackgroundColor="{Binding CategoryColor}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
                                           <Label.GestureRecognizers>
                                               <TapGestureRecognizer
                                    Command="{Binding MyLeftSLTapCommand, Source={RelativeSource AncestorType={x:Type local:MenuViewModel}}}" CommandParameter="{Binding .}" NumberOfTapsRequired="1"
                                 />
                                           </Label.GestureRecognizers>
    
    
                                      </Label>
                                   </Grid>
                               </Border>
                           </ContentView>
                       </DataTemplate>
                   </BindableLayout.ItemTemplate>
               </StackLayout>
    
    
              <StackLayout BindableLayout.ItemsSource="{Binding MenuRight}" Orientation="Vertical">
    
    
                  <BindableLayout.ItemTemplate>
    
    
                      <DataTemplate>
    
    
                          <ContentView >
    
    
                              <Border StrokeThickness="0" WidthRequest="60"  HorizontalOptions="FillAndExpand" >
                                   <Grid>
                                       <Label  TextColor="{DynamicResource SecondaryTextColor}"  Text="{Binding Icon}" BackgroundColor="{Binding CategoryColor}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
                                           <Label.GestureRecognizers>
                                               <TapGestureRecognizer
                        Command="{Binding MyRightSLTapCommand, Source={RelativeSource AncestorType={x:Type local:MenuViewModel}}}" CommandParameter="{Binding .}" NumberOfTapsRequired="1"
                     />
                                           </Label.GestureRecognizers>
    
    
                                      </Label>
                                   </Grid>
                               </Border>
                           </ContentView>
                       </DataTemplate>
                   </BindableLayout.ItemTemplate>
               </StackLayout>
           </HorizontalStackLayout>
          
       </ScrollView>
            
    
    

    As note: I do not have Style="{StaticResource fontelloIcon}", so I remove it when I testing.

    Best Regards, Leon Lu


    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

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.