How to change color of item in a list on Mouse hover.?

Vaibhav Methuku 60 Reputation points
2024-04-01T08:23:09.02+00:00

I'm having a list of item, Whenever any item is selected in that particular list changing the particular color of the item using a trigger. please find the below code.

   <DataTemplate x:Key="SiteTemplate">
       <StackLayout x:Name="siteStack" BackgroundColor="{DynamicResource SelectedItemColor}">
           <StackLayout Margin="15,13,15,13" Spacing="7">
               <Label
                   FontFamily="AppRobotoRegularFont"
                   FontSize="16"
                   LineBreakMode="WordWrap"
                   MaxLines="2"
                   Text="{Binding SiteName}"
                   TextColor="{DynamicResource ClrAccDarkBlue}" />
               <Label FontSize="11" TextColor="{DynamicResource ClrAccDarkBlue}">
                   <Label.FormattedText>
                       <FormattedString>
                           <FormattedString.Spans>
                               <Span Text="{Binding SiteStreet}" />
                               <Span Text=", " />
                               <Span Text="{Binding SiteCity}" />
                           </FormattedString.Spans>
                       </FormattedString>
                   </Label.FormattedText>
               </Label>
           </StackLayout>
           <BoxView Style="{StaticResource NewProjectSeperatorBoxViewStyle}" />
           <StackLayout.GestureRecognizers>
               <TapGestureRecognizer Tapped="Item_Tapped" />
           </StackLayout.GestureRecognizers>
           <StackLayout.Triggers>
               <DataTrigger
                   Binding="{Binding IsSelected}"
                   TargetType="StackLayout"
                   Value="False">
                   <Setter Property="Background" Value="White" />
               </DataTrigger>
           </StackLayout.Triggers>
       </StackLayout>
   </DataTemplate>

I want to change color stack on mouse hover as well, I had tried with the visual state manager as well but not working as expected.

<VisualStateManager.VisualStateGroups>
    <VisualStateGroupList>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="PointerOver">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="{DynamicResource ClrAccLighterBlue}" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="Normal">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="{DynamicResource ClrWhite}" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateGroupList>
</VisualStateManager.VisualStateGroups>

Please let me know how to achieve this functionality.

Thanks,
Vaibhav Methuku.

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

Accepted answer
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 35,571 Reputation points Microsoft Vendor
    2024-04-02T02:23:45.5966667+00:00

    Hello,

    You could use the following xaml code to implement the function of changing the background color when the mouse hover Collection View item.

    <CollectionView  ItemsSource="{Binding Messages}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <VerticalStackLayout>
                   <VisualStateManager.VisualStateGroups>
                       <VisualStateGroup Name="CommonStates">
                            <VisualState Name="Normal">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="Lime" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState Name="PointerOver">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="LightBlue" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Label Text="{Binding Length}"/>
                </VerticalStackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    

    Update:

    This is expected for the issue of VisualState invalidating when Datatrigger and VisualState are mixed.

    The DataTrigger overrides the value of the VisualState. If you want VisualState to be triggered under certain circumstances. You could use the state triggers API.

    Upon further investigation, it was found that the PinterOver in the CollectionView overrides the Selected state, causing this requirement to not be completed using the Visual State.

    For items in the CollectionView that have different colors in the selected and normal state, without affecting the color modification when the pointer enters, you can use MVVM to achieve this.

    Please refer to the key code below:

    Model code:

    public class DotMenuItem : INotifyPropertyChanged // Since modifying the properties in an item requires notifying the xaml page, the model class also needs to inherit this interface.
        {
            public string MenuTitle { get; set; }
            private bool _selected = false;
            public bool IsSelected
            {
                get
                {
                    return _selected;
                }
                set
                {
                    _selected = value;
                    OnPropertyChanged();
                }
            }
            public void OnPropertyChanged([CallerMemberName] string name = "") =>
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            public event PropertyChangedEventHandler? PropertyChanged;
        }
    

    ViewModel class:

    public class MyViewModel : INotifyPropertyChanged
        {
           
            private ObservableCollection<DotMenuItem> _message = new ObservableCollection<DotMenuItem>();
            public event PropertyChangedEventHandler? PropertyChanged;
    
           public ObservableCollection<DotMenuItem> Messages
            {
                get
                {
                    return _message;
                }
                set
                {
                    _message = value;
                    OnPropertyChanged();
                }
            }
            public void OnPropertyChanged([CallerMemberName] string name = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            public MyViewModel()
            {
                Messages.Add(new DotMenuItem { MenuTitle = "test1", IsSelected = false });
                Messages.Add(new DotMenuItem { MenuTitle = "test2", IsSelected = false });
            }
       }
    }
    

    Customize a container layout class so that he can bind the Pledged state and change the background color with Pointer gestures.

    public class MyVerticalLayout: VerticalStackLayout
      {
          public static readonly BindableProperty IsSelectedProperty =
    BindableProperty.Create("IsSelected", typeof(bool), typeof(MyVerticalLayout), false);
          public bool IsSelected
          {
              get => (bool)GetValue(IsSelectedProperty);
              set => SetValue(IsSelectedProperty, value);
          }
    
         public MyVerticalLayout()
          {
              PointerGestureRecognizer pointerGestureRecognizer = new PointerGestureRecognizer();
              pointerGestureRecognizer.PointerEntered += PointerGestureRecognizer_PointerEntered;
              pointerGestureRecognizer.PointerExited += PointerGestureRecognizer_PointerExited;
              this.GestureRecognizers.Add(pointerGestureRecognizer);
          }
          private void PointerGestureRecognizer_PointerEntered(object sender, PointerEventArgs e)
          {this.BackgroundColor = Colors.Gold;
          }
    
         private void PointerGestureRecognizer_PointerExited(object sender, PointerEventArgs e)
          {
              if (this.IsSelected)
              {
                  this.BackgroundColor = Colors.AliceBlue;
              }
              else
              {
                  this.BackgroundColor = Colors.Red;
              }
          }
     }
    

    You can do this via the SelectionChanged method in the CollectionView.

    <CollectionView  ItemsSource="{Binding Messages}" SelectionMode="Multiple" SelectionChanged="CollectionView_SelectionChanged">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <c:MyVerticalLayout BackgroundColor="Red" IsSelected="{Binding IsSelected,Mode=TwoWay}">
                    <Label Text="{Binding MenuTitle}"/>
                </c:MyVerticalLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    

    SelectionChanged method:

    private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.CurrentSelection.Count > e.PreviousSelection.Count) {
            DotMenuItem item = e.CurrentSelection.Last() as DotMenuItem;
            item.IsSelected = true;
        }
        else
        {
            DotMenuItem item = e.PreviousSelection.First() as DotMenuItem;
            item.IsSelected = false;
        }
    }
    

    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