0
votes

Problem

  • Visual state manager does not kick in
  • How do I change background of the selected frame?

Any suggestions of what I am doing wrong?

enter image description here

I need to create an horizontal list with a set of frames that when selected change background color.

The obvious implementation would be a collectionView and that has a SelectedItem that would just work , so what is the problem with that?

Well if you have a pancakeView/frame with rounded corners in iOS you can see the grey background and its a bug reported in xamarin forms.

So I decided to implement a bindableLayout, this works fine however I have tried all sorts but I cannot change the background color of the pancake/frame and a label on selection , below is what I have done

MAIN PAGE

        <ContentPage.Resources>
            <ResourceDictionary>
                <Style TargetType="Grid">
                    <Setter Property="VisualStateManager.VisualStateGroups">
                        <VisualStateGroupList>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="Focused">
                                    <VisualState.Setters>
                                        <Setter Property="BackgroundColor" Value="LightSkyBlue" />
                                        <Setter TargetName="LabelA" Property="Label.TextColor" Value="Red"/>
                                        <Setter TargetName="Labelb" Property="Label.TextColor" Value="Red"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateGroupList>
                    </Setter>
                </Style>
            </ResourceDictionary>
        </ContentPage.Resources>
            <FlexLayout x:Name="Flex" 
                        Direction="Row" 
                        BindableLayout.ItemsSource="{Binding Cities}" 
                        Position="Relative" 
                        AlignItems="Start" 
                        FlowDirection="LeftToRight" 
                        JustifyContent="SpaceEvenly">
                <BindableLayout.ItemTemplate>
                    <DataTemplate>
                        <Grid x:Name="myGrid" Padding="8,0" FlexLayout.AlignSelf="Start" >
                            <pancakeView:PancakeView x:Name="myPancake" 
                                                     Padding="20" 
                                                     Margin="5" 
                                                     CornerRadius="5" 
                                                     WidthRequest="60" 
                                                     HeightRequest="60" 
                                                     BackgroundColor="White" >
                                <pancakeView:PancakeView.Border>
                                    <pancakeView:Border Thickness="1" Color="Blue"  />
                                </pancakeView:PancakeView.Border>

                                <StackLayout >
                                    <Label x:Name="LabelA" Margin="0,0,0,0"
                                                           Text="{Binding Name }"
                                                           TextColor="Gray"
                                                           HorizontalOptions="Center" VerticalOptions="Center">
                                    </Label>
                                    <Label x:Name="Labelb" VerticalOptions="EndAndExpand"
                                                           HorizontalTextAlignment="Center" 
                                                           TextColor="Gray" 
                                                           FontSize="12"
                                                           Text="SomeText Here" />
                                </StackLayout>
                                <pancakeView:PancakeView.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped">

                                    </TapGestureRecognizer>
                                </pancakeView:PancakeView.GestureRecognizers>
                            </pancakeView:PancakeView>
                        </Grid>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </FlexLayout>

    </ContentPage>

MAIN PAGE CODE BEHIND

    using System;
    using Xamarin.Forms;

    namespace BlankApp2.Views
    {
        public partial class MainPage
        {
            string currentColorState = "Normal";
            public MainPage()
            {
                InitializeComponent();
            }

            private void TapGestureRecognizer_OnTapped(object sender, EventArgs e)
            {
                currentColorState = currentColorState == "Normal" ? "Focused" : "Normal";

                //below has errors since "myPancake, LabelA Labelb are not recognized WHY????

                //  VisualStateManager.GoToState(myPancake,_currentColorState);
                //  VisualStateManager.GoToState(LabelA, _currentColorState);
                // VisualStateManager.GoToState(Labelb, _currentColorState);
            }
        }
    }

VIEWMODEL

    using Prism.Navigation;
    using System.Collections.ObjectModel;

    namespace BlankApp2.ViewModels
    {
        public class MainPageViewModel : ViewModelBase
        {
            public MainPageViewModel(INavigationService navigationService)
                : base(navigationService)
            {
                Title = "Main Page";
                Cities = GetCities();

            }
            private ObservableCollection<City> cities;
            public ObservableCollection<City> Cities
            {
                get => cities;
                set => SetProperty(ref cities, value);
            }
            private ObservableCollection<City> GetCities()
            {
                var list = new ObservableCollection<City>
                {
                    new City {Name = "London"},
                    new City {Name = "Rome"},
                    new City {Name = "New York"}
                };

                return list;
            }
        }
        public class City
        {
            public string Name { get; set; }
        }
    }
1

1 Answers

1
votes

Try to add VisualStateManager.VisualStateGroups your frame/pancakeviw(Here I'm testing with frame).

create a custom frame:

class MyFrame :Frame
{
    public bool IsFoucs { get; set; }
}

the page.xaml:

<ContentPage.Resources>
    <ResourceDictionary>
        <Style TargetType="local:MyFrame">
            <Setter Property="VisualStateManager.VisualStateGroups">
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" >
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="White" />
                                <Setter TargetName="LabelA" Property="Label.TextColor" Value="Gray"/>
                                <Setter TargetName="Labelb" Property="Label.TextColor" Value="Gray"/>
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Focused">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="LightSkyBlue" />
                                <Setter TargetName="LabelA" Property="Label.TextColor" Value="Red"/>
                                <Setter TargetName="Labelb" Property="Label.TextColor" Value="Red"/>
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </Setter>
        </Style>
    </ResourceDictionary>
</ContentPage.Resources>
<FlexLayout x:Name="Flex" 
                    Direction="Row" 
                    BindableLayout.ItemsSource="{Binding Cities}" 
                    Position="Relative" 
                    AlignItems="Start" 
                    FlowDirection="LeftToRight" 
                    JustifyContent="SpaceEvenly">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Grid x:Name="myGrid" Padding="8,0" FlexLayout.AlignSelf="Start" >
                <local:MyFrame x:Name="myPancake" 
                                                 Padding="20" 
                                                 Margin="5" 
                                                 CornerRadius="5" 
                                                 WidthRequest="60" 
                                                 HeightRequest="60" 
                                                 BorderColor="Blue"
                                                 BackgroundColor="White" >
           

                    <StackLayout >
                        <Label x:Name="LabelA" Margin="0,0,0,0"
                                                       Text="{Binding .}"
                                                       TextColor="Gray"
                                                       HorizontalOptions="Center" VerticalOptions="Center">
                        </Label>
                        <Label x:Name="Labelb" VerticalOptions="EndAndExpand"
                                                       HorizontalTextAlignment="Center" 
                                                       TextColor="Gray" 
                                                       FontSize="12"
                                                       Text="SomeText Here" />
                    </StackLayout>
                    <local:MyFrame.GestureRecognizers>
                        <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped">

                        </TapGestureRecognizer>
                    </local:MyFrame.GestureRecognizers>
                </local:MyFrame>
            </Grid>
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</FlexLayout>

then in the page.cs:

private void TapGestureRecognizer_OnTapped(object sender, EventArgs e)
    {
        foreach (var item in Flex.Children)
        {
            MyFrame frame = (MyFrame)item.FindByName("myPancake");
            frame.IsFoucs = false;
            VisualStateManager.GoToState(frame, "Normal");
        }
        MyFrame myFrame = sender as MyFrame;
        myFrame.IsFoucs = !myFrame.IsFoucs;
        VisualStateManager.GoToState(myFrame, myFrame.IsFoucs ? "Focused" : "Normal");
    }

the effect is like below:

enter image description here