SegmentedControl icon indicating copy to clipboard operation
SegmentedControl copied to clipboard

SelectedSegment Binding Broken Within DataTemplate

Open Jyosua opened this issue 8 years ago • 3 comments

Hi! We were trying to use this control within the DataTemplate of a ListView and found that the SelectedSegment binding was not working after the first change on Android. On iOS, it only seems to stop working if you manually toggle the control before programmatically changing the bound property. I was able to reproduce this in a small sample project. Below are the MainPage.xaml, corresponding codebehind, and supporting code that I reproduced this on.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SampleApp2"
             xmlns:abstractions="clr-namespace:SegmentedControl.FormsPlugin.Abstractions;assembly=SegmentedControl.FormsPlugin.Abstractions"
             x:Class="SampleApp2.MainPage">
    <StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
        <Button Text="Check All" Clicked="OnClick" />
        <ListView HasUnevenRows="False" HorizontalOptions="FillAndExpand" BackgroundColor="Black"
                    VerticalOptions="FillAndExpand" x:Name="AttendeeList" RowHeight="80">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell Height="100">
                        <StackLayout VerticalOptions="CenterAndExpand">
                            <abstractions:SegmentedControl x:Name="AttendanceControl" SelectedSegment="{Binding Status}" SelectedTextColor="White" TintColor="{Binding StatusColor}">
                                <abstractions:SegmentedControl.Children>
                                    <abstractions:SegmentedControlOption Text="Missing"/>
                                    <abstractions:SegmentedControlOption Text="Turned"/>
                                    <abstractions:SegmentedControlOption Text="Attended"/>
                                </abstractions:SegmentedControl.Children>
                            </abstractions:SegmentedControl>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace SampleApp2
{
	public partial class MainPage : ContentPage
	{
                private ObservableCollection<Attendee> _attendees;

		public MainPage()
		{
			InitializeComponent();
			_attendees = new ObservableCollection<Attendee>() { new Attendee(0), new Attendee(1), new Attendee(2) };
			AttendeeList.ItemsSource = _attendees;
		}

		public void OnClick(object sender, EventArgs e)
		{
			foreach (var item in _attendees)
				item.Status = item.Status == 2 ? 0 : 2;
		}
	}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using Xamarin.Forms;

namespace SampleApp2
{
    public class Attendee : INotifyPropertyChanged
    {
        public Attendee(int status)
        {
            Status = status;
        }

        private int _status;
        public int Status
        {
            get => _status;
            set
            {
                _status = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(StatusColor));
            }
        }

        public Color StatusColor
        {
            get
            {
                switch (Status)
                {
                    case 0:
                        return Color.Gray;
                    case 1:
                        return Color.Yellow;
                    case 2:
                        return Color.Green;
                    default:
                        return Color.Gray;
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The TintColor binding appears to continue to work in any case. It's just the SelectedSegment binding that stops working.

Jyosua avatar Jan 23 '18 20:01 Jyosua

I put the entire sample project up in a repository here: https://github.com/Jyosua/SegmentedControlBug_SampleProject

Jyosua avatar Jan 23 '18 21:01 Jyosua

@alexrainman Are you able to look into this? I am also having this problem... Thank you!

ryanherman avatar Jan 29 '18 21:01 ryanherman

Turns out it is an easy fix...

SelectedSegment="{Binding Status, Mode=TwoWay}" 

ryanherman avatar Feb 01 '18 01:02 ryanherman