This is a migrated thread and some comments may be shown as answers.

Selected visual state not applied to ItemTemplate

1 Answer 1594 Views
ListView
This is a migrated thread and some comments may be shown as answers.
Joshua
Top achievements
Rank 2
Joshua asked on 08 Apr 2020, 05:46 PM

Hello,

I'm trying to migrate from CollectionView to RadListView and one of the challenges I'm facing is that the Selected visual state is not applied to the cell. For example, consider the following code:

<ContentPage>
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="itemTemplate">
                <Frame>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroupList>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="Selected">
                                    <VisualState.Setters>
                                        <Setter TargetName="someSignature"
                                                Property="controls:SignaturePadView.IsEnabled"
                                                Value="True" />
                                        <Setter TargetName="someSignature"
                                                Property="controls:SignaturePadView.SignatureLineColor"
                                                Value="#FF4081" />
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateGroupList>
                    </VisualStateManager.VisualStateGroups>
                    <StackLayout>
                        <Label Text="Name:" />
                        <Label Text="{Binding Path=Name}" />
                        <controls:SignaturePadView x:Name="someSignature" IsEnabled="False">
                        </controls:SignaturePadView>
                    </StackLayout>
                </Frame>
            </DataTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>
     
    <telerikDataControls:RadListView x:Name="listView"
                                    ItemsSource="{Binding Path=Items}"
                                    ItemTemplate="{StaticResource itemTemplate}"
                                    SelectedItem="{Binding Path=SelectedItem">
        <telerikDataControls:RadListView.SelectedItemStyle>
            <telerikListView:ListViewItemStyle BackgroundColor="LightSkyBlue" />
        </telerikDataControls:RadListView.SelectedItemStyle>
    </telerikDataControls:RadListView>
</ContentPage>

 

In the example, I only want to enable the signature pad when the cell is selected. However, since the Selected visual state is not applied to the parent view of the DataTemplate, the code does not work. This is contrary to the behavior of the Microsoft collection view controls, i.e. ListView and CollectionView.

Is there a way I can have RadListView apply the Selected visual state to the view I define in the DataTemplate? If not, what can I trigger off of?

Thanks,

Josh

 

 

1 Answer, 1 is accepted

Sort by
1
Accepted
Lance | Senior Manager Technical Support
Telerik team
answered on 08 Apr 2020, 09:21 PM

Hi Joshua,

Thank you for the code, I see two issues with the approach let me share the ideas and and solution with you.

Problem 1 - Incorrect DataTemplate

The first problem I see here is that the DataTemplate is not using the ListViewTemplateCell. The paradigm for RadListView is different than a vanilla CollectionView as the RadListView is an advanced native component with a common XamarinForms API surface layer.

  • For just plain text binding, you can use a ListViewTextCell.
  • For custom content, then you'd use a ListViewTemplateCell.

Please visit the ListView Cells documentation to learn more. For example:

<DataTemplate x:Key="itemTemplate">
    <listView:ListViewTemplateCell>
        <!-- Your custom content here -->
    </listView:ListViewTemplateCell>
</DataTemplate>

Issue 2 - TargetName based Setter

Okay, let's move on to the crux of your question. The VisualState Setters did not introduce support for TargetName until the very recent release of Xamarin.Forms (v4.5).

Currently, Telerik UI for Xamarin supports a minimum version of Xamarin.Forms 4.1. We are working on updating to Xamarin.Forms 4.5 soon and may be able provide support for VisualStates and Selected state. at this time, it is not supported.

Ultimately, there is no extra overhead for the data context of the cell. It's purely the data item itself, so there's no state to hold an extra "IsSelected" value.  What I mean is, either the item is in the SelectedItems collection or it isn't.

This does give you a route to an easy solution to achieve your goal.

Solution

Until this is supported, one potential solution is to use a DataTrigger on a IsSelected property of your data model. when the selection changes, you can trigger the model's value in SelectionChanged.

For example, you'd add an IsSelected property to the data model (making sure IsSelected calls OnPropertyChanged when it is set):

public class Item : NotifyPropertyChangedBase { private bool isSelected;

public string Name { get; set; } publicbool IsSelected { get => isSelected; set => UpdateValue(ref isSelected, value); } }

 

In the ItemTemplate, use that new IsSelected property to make all the changes you want. I've moved the Setters you've defined from the VisualStateManager into a DataTrigger instead:

 

<DataTemplate x:Key="itemTemplate">
    <listView:ListViewTemplateCell>
        <Frame>
            <StackLayout>
                <Label Text="Name:" />
                <Label Text="{Binding Name}" />
                <local:SignaturePadView x:Name="someSignature">
                    <local:SignaturePadView.Triggers>
                        <DataTrigger Binding="{Binding IsSelected}"
                                     TargetType="local:SignaturePadView"
                                     Value="True">
                            <Setter Property="IsEnabled" Value="True" />
                            <Setter Property="SignatureLineColor" Value="#FF4081" />
                        </DataTrigger>
                    </local:SignaturePadView.Triggers>
                </local:SignaturePadView>
            </StackLayout>
        </Frame>
    </listView:ListViewTemplateCell>
</DataTemplate>

The final piece to complete is the actually toggling the IsSelected value on the item that was just selected. There are many ways you can do this, a common way would be to use the SelectionChanged event handler.

However, since you're already binding to a view model property, just change it to a TwoWay binding and toggle it there.

view:

<telerikDataControls:RadListView ItemsSource="{Binding Items}"
                                 SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                                 ItemTemplate="{StaticResource itemTemplate}"/>

viewmodel:

public class MainViewModel : NotifyPropertyChangedBase
{
    private Item selectedItem;

    public MainViewModel()
    {
        Items = new ObservableCollection<Item>(Enumerable.Range(1, 20).Select(i => new Item
        {
            Name = $"Item {i}"
        }));

        SelectedItem = Items.FirstOrDefault();
    }

    public ObservableCollection<Item> Items { get; set; }

    public Item SelectedItem
    {
        get => selectedItem;
        set
        {
            UpdateValue(ref selectedItem, value);
            ToggleIsSelected();
        }
    }

    private void ToggleIsSelected()
    {
        foreach (var item in Items)
        {
            item.IsSelected = item != SelectedItem;
        }
    }
}

I've attached the completed code, here's the result at runtime on ios (I used a Button to act as a placeholder for signaturePad)


 

Extra - Productivity Tips

You could also auto-complete much of this code by using the Telerik UI for Xamarin Toolbox that got installed to Visual Studio when you installed UI for Xamarin.

For example, if you drag this selection into the XAML, it would complete all of the code with the ItemTemplate setup with a couple demo Labels.

I hope this was helpful information and not only gets you past the selection question, but adds some tips to help you be more productive.

As I mentioned in the other forum reply, if you'd like more support in a prompt fashion that forums can provide, take advantage of your Support license and open a Support Ticket here.

Regards,
Lance | Team Lead - US DevTools Support
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
ListView
Asked by
Joshua
Top achievements
Rank 2
Answers by
Lance | Senior Manager Technical Support
Telerik team
Share this question
or