Как получить индексы элементов Xamarin CollectionView?

#c# #xaml #xamarin #collectionview #itemtemplate

#c# #xaml #xamarin #collectionview #itemtemplate

Вопрос:

У меня есть CollectionView:

 <CollectionView Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="1" x:Name="SomeCollection"
        ItemsLayout="VerticalList">
<CollectionView.ItemTemplate>
    <DataTemplate>
        <StackLayout Orientation="Horizontal" Padding="3" Spacing="0">
            <Label WidthRequest="90" HeightRequest="20" Text="{Binding SomeItemText}" BackgroundColor="Black" TextColor="White"
               VerticalTextAlignment="Center" HorizontalTextAlignment="Center" />
            <Button WidthRequest="36" HeightRequest="36" CornerRadius="0" ImageSource="plus_thick.xml" BackgroundColor="Green"
                Clicked="Duplicate_Clicked" />
            <Button WidthRequest="36" HeightRequest="36" CornerRadius="0" ImageSource="close_thick.xml" BackgroundColor="Red" 
                Clicked="Remove_Clicked" />
        </StackLayout>
    </DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
 

У каждого элемента в коллекции есть дубликат и кнопка удаления. Нажав на кнопку, я хотел бы дублировать / удалить элемент, но в CollectionView нет индексов для элементов.

Не могли бы вы помочь мне с пользовательским средством визуализации или даже с чем-то более коротким и простым?

Ответ №1:

О получении текущего индекса элемента collectionview с помощью команды Button, я делаю один пример, который вы можете посмотреть:

  <StackLayout>
        <CollectionView
            x:Name="SomeCollection"
            ItemsLayout="VerticalList"
            ItemsSource="{Binding items}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout
                        Padding="3"
                        Orientation="Horizontal"
                        Spacing="0">
                        <Label
                            BackgroundColor="Black"
                            HeightRequest="20"
                            HorizontalTextAlignment="Center"
                            Text="{Binding SomeItemText}"
                            TextColor="White"
                            VerticalTextAlignment="Center"
                            WidthRequest="90" />
                        <Button
                            BackgroundColor="Green"
                            Command="{Binding BindingContext.duplicatecommand, Source={x:Reference SomeCollection}}"
                            CommandParameter="{Binding}"
                            CornerRadius="0"
                            HeightRequest="36"
                            Text="duplicate item"
                            WidthRequest="36" />
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>

 public partial class Page13 : ContentPage
{
    public ObservableCollection<someitems> items { get; set; }
    public ICommand duplicatecommand { get; set; }
    public Page13()
    {
        InitializeComponent();
        items = new ObservableCollection<someitems>()
        {
            new someitems(){SomeItemText="test 1"},
            new someitems(){SomeItemText="test 2"},
            new someitems(){SomeItemText="test 3"},
            new someitems(){SomeItemText="test 4"},
            new someitems(){SomeItemText="test 5"},
            new someitems(){SomeItemText="test 6"}
        };

        duplicatecommand = new Command<someitems>(getindexfun);
        this.BindingContext = this;
    }
    private void getindexfun(someitems item)
    {
        int index = items.IndexOf(item);
    }
}

public class someitems
{
    public string SomeItemText { get; set; }
}
 

Ответ №2:

Вместо того, чтобы использовать события щелчка, я бы привязал кнопки к a Command<T> .

Таким образом, в ViewModel, где у вас есть ItemsSource, вы можете просто проверить, какой индекс у элемента ViewModel, который вы передаете в команду в качестве параметра. Итак, в ViewModel добавьте что-то вроде этого:

 public Command<ItemViewModel> RemoveItemCommand { get; }

ctor() // this is the ViewModel constructor
{
    RemoveItemCommand = new Command<ItemViewModel>(DoRemoveItemCommand);
}

private void DoRemoveItemCommand(ItemViewModel model)
{
    // do stuff to remove
    // probably something like:
    Items.Remove(model);
    // or get the index like:
    var index = Items.IndexOf(model);
}
 

Затем вы можете связать эту команду следующим образом:

 <Button
    WidthRequest="36"
    HeightRequest="36"
    CornerRadius="0"
    ImageSource="close_thick.xml"
    BackgroundColor="Red"
    Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemViewModel}}, Path=RemoveItemCommand}"
    CommandParameter="{Binding}" />
 

Комментарии:

1. Честно говоря, мое приложение было настолько простым, что до сих пор у меня не было ViewModel. После реализации я получаю следующую ошибку: свойство ‘ElementName’ не было найдено в типе ‘BindingExtension’. После удаления ElementName команда button не запускается.

2. Ах да, в Xamarin все немного по-другому. Формы по сравнению с WPF. Позвольте мне это исправить.

3. Подробнее об относительных привязках читайте в официальных документах здесь: docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals /…

4. Спасибо за ссылку. Привязка к предку выдает ошибку «Тип ItemViewModel не найден в xmlns», поэтому мне приходится закомментировать строку [assembly: XamlCompilation(XamlCompilationOptions. Скомпилировать)] в AssemblyInfo.cs. Команда button по-прежнему не срабатывает, что бы я ни пытался. Простая кнопка без предка работает нормально.

5. @Tomo Пожалуйста, посмотрите мой ответ и попробуйте еще раз.