Sharpnado.CollectionView icon indicating copy to clipboard operation
Sharpnado.CollectionView copied to clipboard

How to implement item selection on HorizontalListView?

Open ske66 opened this issue 4 years ago • 6 comments

The Drag and Drop functionality is great, but why isn't there any SelectedItem property? Id say this is one of the most important properties of a ListView (apart from ItemSource).

ske66 avatar Apr 23 '20 14:04 ske66

You can easily implement it with the TapCommand by adding an IsSelected property in your view model.

roubachof avatar Apr 23 '20 16:04 roubachof

Do you have any examples?

ske66 avatar Apr 23 '20 17:04 ske66

Well as I said add a IsSelected property in your items ViewModel (let's call them ItemViewModel). Then bind an ICommand to the TapCommand of the HorizontalListView (let's call it ListTapCommand). In ListTapCommand just implement the selection logic of your view model items:

class ItemViewModel
{
	public bool IsSelected { get; set; }
}

class ListViewModel
{
	public ListViewModel()
	{
		ListTapCommand = new Command(OnListTap);
	}

	public ObservableCollection<ItemViewModel> Items { get; }

	public ICommand ListTapCommand { get; }

	public void OnListTap(ItemViewModel tappedItem)
	{

		// One and only one selectable element
		foreach (var item in Items)
		{
			item.IsSelected = item == tappedItem;
		}

		// OR
		// One or zero selectable element
		foreach (var item in Items)
		{
			item.IsSelected = item == tappedItem ? !item.IsSelected : false;
		}

		// OR
		// Multiple selection 
		tappedItem.IsSelected = !tappedItem.IsSelected;
	}
}

roubachof avatar Apr 23 '20 19:04 roubachof

ah thank you. This helps us out a lot.

ske66 avatar Apr 23 '20 20:04 ske66

I will leave this open since it could help others as well.

roubachof avatar Apr 24 '20 00:04 roubachof

Actually thanks for re-opening this. Just wanted to include a full code snippet for anyone in the future. Please correct me if my implementation is incorrect.

ListPage.cs

     <renderedViews:HorizontalListView
            ColumnCount="1"
            ListLayout="Grid"
            EnableDragAndDrop="True"
            ItemHeight="80"
            ItemSpacing="2"
            Margin="8"
            CurrentIndex="0"
            TapCommand="{Binding ListTapCommand}"
            VerticalOptions="FillAndExpand" ItemsSource="{Binding ListItems}">
        <renderedViews:HorizontalListView.ItemTemplate>
            <DataTemplate>
                <renderedViews:DraggableViewCell IsDraggable="True" x:Name="DraggableViewCell" >
                    <ContentView>
                        <renderedViews:MaterialFrame Margin="4"
                                     Elevation="4">
                            <Frame.Triggers>
                                <DataTrigger Binding="{Binding Source={x:Reference DraggableViewCell}, Path=IsDragAndDropping}"
                                         TargetType="renderedViews:MaterialFrame"
                                         Value="True">
                                    <Setter Property="Elevation" Value="8" />
                                </DataTrigger>
                            </Frame.Triggers>
                            <StackLayout Orientation="Horizontal" Margin="16" VerticalOptions="Center">
                                <ui:MaterialLabel Text="{Binding Name}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
                                <Image Source="printer.png" HorizontalOptions="EndAndExpand"/>
                            </StackLayout>
                        </renderedViews:MaterialFrame>
                    </ContentView>
                </renderedViews:DraggableViewCell>
            </DataTemplate>
        </renderedViews:HorizontalListView.ItemTemplate>
    </renderedViews:HorizontalListView>`

ListPageViewModel.cs

public class ListPageViewModel
    {
        private ObservableCollection<MyListItemModel> ListItems = new ObservableCollection<MyListItemModel>();

        public ObservableCollection<MyListItemModel> ListItems
        {
            get => _strains;
            set => SetProperty(ref _strains, value);
        }

        public ICommand ListTapCommand { get; }

        public ListPageViewModel()
        {
            ListTapCommand = new Command(OnListTap);
            
            ListItems.Add(new MyListItemModel { Name = "John Doe" });
            ListItems.Add(new MyListItemModel { Name = "Jane Doe" });
        }

        public void OnListTap(object obj)
        {
            var item = (MyListItemModel) obj;

            item.IsSelected = !item.IsSelected;
        }

MyListItemModel.cs

    public class MyListItem
    {
        public string Name { get; set; }
        public bool IsSelected { get; set; }
    }

ske66 avatar Apr 24 '20 07:04 ske66