Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Xamarin Forms: How to Change the textcolor of Collectionview SelectedItem?

SreeeeSreeee INMember ✭✭✭✭✭

I have a CarouselPage having 5 children and every child has a horizontal collection view. When selecting an item in Collectionview or swiping the pages, I need to give a different text color and need to add an underline for the selected item. I have tried like below:

CarouselHomePage.cs

public partial class CarouselHomePage : CarouselPage
{
    public List<Activity> activityList { get; set; }
    public CarouselHomePage()
    {
        InitializeComponent(); 
        activityList = new List<Activity>();
        AddActivities();

        MessagingCenter.Subscribe<App, string>((App)Xamarin.Forms.Application.Current, "child", (s, child) =>
        {
            CurrentPage = Children[Int32.Parse(child)];
        });
    }

    private void AddActivities()
    {
        activityList.Add(new Activity() { Title = "PageNumber1" });
        activityList.Add(new Activity() { Title = "PageNumber2" });
        activityList.Add(new Activity() { Title = "PageNumber3" });
        activityList.Add(new Activity() { Title = "PageNumber4" });
        activityList.Add(new Activity() { Title = "PageNumber5" });
        AddChild(activityList);
    }

    public void AddChild(List<Activity> activityList)
    {
        this.Children.Add(new PageNumber1(activityList));
        this.Children.Add(new PageNumber2(activityList));
        this.Children.Add(new PageNumber3(activityList));
        this.Children.Add(new PageNumber4(activityList));
        this.Children.Add(new PageNumber5(activityList));
    }
}

Activity.cs

public class Activity
{
    public string Title { get; set; }

    public bool visibility { get; set; }
    public bool Visibility
    {
        set
        {
            if (value != null)
            {
                visibility = value;
                NotifyPropertyChanged();
            }
        }
        get
        {
            return visibility;
        }
    }

    private Color textColor;
    public Color TextColor
    {
        set
        {
            if (value != null)
            {
                textColor = value;
                NotifyPropertyChanged();
            }
        }
        get
        {
            return textColor;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

PageNumber1.xaml

<ContentPage.Content>
    <StackLayout Orientation="Vertical">
        <CollectionView 
            SelectionMode="Single"
            x:Name="ActivityList"
            Margin="5,10,5,10"
            SelectionChanged="TagItemTapped"
            ItemsLayout="HorizontalList">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout 
                        Orientation="Vertical"
                        Margin="15">

                        <Label
                            TextColor="{Binding TextColor}"
                            HorizontalTextAlignment="Center"
                            VerticalTextAlignment="Center"
                            Text="{Binding Title}">
                            <Label.FontSize>
                                <OnIdiom x:TypeArguments="x:Double">
                                    <OnIdiom.Phone>18</OnIdiom.Phone>
                                    <OnIdiom.Tablet>27</OnIdiom.Tablet>
                                    <OnIdiom.Desktop>18</OnIdiom.Desktop>
                                </OnIdiom>
                            </Label.FontSize>
                        </Label>

                        <BoxView 
                            HeightRequest="2"
                            IsVisible="{Binding Visibility}"
                            BackgroundColor="{Binding TextColor}" 
                            HorizontalOptions="CenterAndExpand"
                            VerticalOptions="Start"/>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
            <CollectionView.HeightRequest>
                <OnIdiom x:TypeArguments="x:Double">
                    <OnIdiom.Phone>30</OnIdiom.Phone>
                    <OnIdiom.Tablet>60</OnIdiom.Tablet>
                    <OnIdiom.Desktop>30</OnIdiom.Desktop>
                </OnIdiom>
            </CollectionView.HeightRequest>
        </CollectionView>

        <Label Text="Welcome to PageNumber1"
            VerticalOptions="CenterAndExpand" 
            HorizontalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage.Content>

PageNumber1.xaml.cs

public partial class PageNumber1 : ContentPage
{
    public PageNumber1(List<Activity> activityList)
    {
        InitializeComponent();
        if (activityList == null)
        {
            ActivityList.IsVisible = false;
        }
        else
        {
            for (int i = 0; i < activityList.Count; i++)
            {
                if (activityList[i].Title == "PageNumber1")
                {
                    activityList[i].TextColor = Color.FromHex("#26b4d8");
                    activityList[i].Visibility = true;
                }
                else
                {
                    activityList[i].TextColor = Color.Gray;
                    activityList[i].Visibility = false;
                }
            }
            ActivityList.ItemsSource = activityList;
        }
    }
    public void TagItemTapped(object sender, SelectionChangedEventArgs e)
    {
        var selectedItem = (e.CurrentSelection.FirstOrDefault() as Activity);
        if (selectedItem != null)
        {
            string childnumber = "";
            if (selectedItem.Title == "PageNumber1")
            {
                childnumber = "0";
            }
            else if (selectedItem.Title == "PageNumber2")
            {
                childnumber = "1";
            }
            else if (selectedItem.Title == "PageNumber3")
            {
                childnumber = "2";
            }
            else if (selectedItem.Title == "PageNumber4")
            {
                childnumber = "3";
            }
            else if (selectedItem.Title == "PageNumber5")
            {
                childnumber = "4";
            }
            MessagingCenter.Send<App, string>((App)Xamarin.Forms.Application.Current, "child", childnumber);
        }
    }
}

I have added the same code on all the other child pages with the corresponding title in the if statement. But the selected page title color is not working and underline is not showing.

Screenshot:

enter image description here

Also if I select the last item in the collectionview, I need to scroll the collection on the last child to the last item. For this I have used ScrollTo feature of Collectioview. But that is also not working.

protected override void OnAppearing()
{
    ActivityList.ScrollTo(4);
}

The above code will work if I manually swipe the pages. When directly tap the collectionview item, the scrolling is not working.

I have uploaded a sample project here.

Best Answers

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    If so, you have to create different instances of activities for different pages. I modified the CarouselHomePage like:

    public partial class CarouselHomePage : CarouselPage
    {
        //public List<Activity> activityList { get; set; }
        public CarouselHomePage()
        {
            InitializeComponent(); 
    
    
            this.Children.Add(new PageNumber1(AddActivities()));
            this.Children.Add(new PageNumber2(AddActivities()));
            this.Children.Add(new PageNumber3(AddActivities()));
            this.Children.Add(new PageNumber4(AddActivities()));
            this.Children.Add(new PageNumber5(AddActivities()));
    
            MessagingCenter.Subscribe<App, string>((App)Xamarin.Forms.Application.Current, "child", (s, child) =>
            {
                CurrentPage = Children[Int32.Parse(child)];
            });
        }
    
        private List<Activity> AddActivities()
        {
            List<Activity> activityList = new List<Activity>();
            activityList.Add(new Activity() { Title = "PageNumber1" });
            activityList.Add(new Activity() { Title = "PageNumber2" });
            activityList.Add(new Activity() { Title = "PageNumber3" });
            activityList.Add(new Activity() { Title = "PageNumber4" });
            activityList.Add(new Activity() { Title = "PageNumber5" });
            return activityList;
        }
    
        //public void AddChild(List<Activity> activityList)
        //{
        //    this.Children.Add(new PageNumber1(activityList));
        //    this.Children.Add(new PageNumber2(new List<Activity>(activityList)));
        //    this.Children.Add(new PageNumber3(new List<Activity>(activityList)));
        //    this.Children.Add(new PageNumber4(new List<Activity>(activityList)));
        //    this.Children.Add(new PageNumber5(new List<Activity>(activityList)));
        //}
    }
    

    And adjust the height of the collection view to make the bottom box view visible.

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    Add some delay in OnAppearing:

    protected async override void OnAppearing()
    {
        await Task.Delay(100);
        int scrollChild = Int32.Parse(Application.Current.Properties["lessonfib"].ToString());
        ActivityList.ScrollTo(scrollChild);
    }
    

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    The most appropriate control here is Carousel View:
    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/carouselview/
    Put a collection view at the top of a page as the title. When it's selection changes move the carousel view to the corresponding items. So does the carousel view.
    Here is the effect:

    Attached my sample here.

  • SreeeeSreeee INMember ✭✭✭✭✭

    @LandLu Thanks for your answer.

    But I need to do this feature with different content pages like the sample. On every content page, I am showing different data, so with a single content page, I can't do all the features. I have uploaded a sample video here.

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    If so, you have to create different instances of activities for different pages. I modified the CarouselHomePage like:

    public partial class CarouselHomePage : CarouselPage
    {
        //public List<Activity> activityList { get; set; }
        public CarouselHomePage()
        {
            InitializeComponent(); 
    
    
            this.Children.Add(new PageNumber1(AddActivities()));
            this.Children.Add(new PageNumber2(AddActivities()));
            this.Children.Add(new PageNumber3(AddActivities()));
            this.Children.Add(new PageNumber4(AddActivities()));
            this.Children.Add(new PageNumber5(AddActivities()));
    
            MessagingCenter.Subscribe<App, string>((App)Xamarin.Forms.Application.Current, "child", (s, child) =>
            {
                CurrentPage = Children[Int32.Parse(child)];
            });
        }
    
        private List<Activity> AddActivities()
        {
            List<Activity> activityList = new List<Activity>();
            activityList.Add(new Activity() { Title = "PageNumber1" });
            activityList.Add(new Activity() { Title = "PageNumber2" });
            activityList.Add(new Activity() { Title = "PageNumber3" });
            activityList.Add(new Activity() { Title = "PageNumber4" });
            activityList.Add(new Activity() { Title = "PageNumber5" });
            return activityList;
        }
    
        //public void AddChild(List<Activity> activityList)
        //{
        //    this.Children.Add(new PageNumber1(activityList));
        //    this.Children.Add(new PageNumber2(new List<Activity>(activityList)));
        //    this.Children.Add(new PageNumber3(new List<Activity>(activityList)));
        //    this.Children.Add(new PageNumber4(new List<Activity>(activityList)));
        //    this.Children.Add(new PageNumber5(new List<Activity>(activityList)));
        //}
    }
    

    And adjust the height of the collection view to make the bottom box view visible.

  • SreeeeSreeee INMember ✭✭✭✭✭

    @LandLu I will check this and update you.

  • SreeeeSreeee INMember ✭✭✭✭✭

    @LandLu I have asked one more thing in the question about scrolling the collectionview.

    If I select the last item in the collectionview, I need to scroll the collectionview on the last child to the last item. For this I have used ScrollTo feature of Collectioview. But that is also not working.

    protected override void OnAppearing()
    {
        ActivityList.ScrollTo(4);
    }
    

    The above code will work if I manually swipe the pages. When directly tap the collectionview item, the scrolling is not working. Could you please help me to find a solution for that?

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    Add some delay in OnAppearing:

    protected async override void OnAppearing()
    {
        await Task.Delay(100);
        int scrollChild = Int32.Parse(Application.Current.Properties["lessonfib"].ToString());
        ActivityList.ScrollTo(scrollChild);
    }
    
Sign In or Register to comment.