UWP - MVVM - удалить элемент ListView с помощью кнопки ItemTemplate - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть экран со списком элементов, на котором пользователь может нажать кнопку, чтобы удалить соответствующий элемент из списка.

Я пытаюсь сделать это с помощью MVVM.

Но элемент не знает о содержащем списке, когда получает действие. Я видел некоторые ответы здесь и там, но ни один из них не использовал готовые функции MVVM, которые есть в моей среде Например, тот, который использует PRISM (не знаю, должен ли я использовать это тоже, это стандарт?):

Вот XAML:

<ListView ItemsSource="{Binding MyItemList}" SelectionMode="None" ScrollViewer.VerticalScrollMode="Disabled" ItemContainerTransitions="{x:Null}"> 
    <ListView.ItemTemplate>
        <DataTemplate >
            <Grid Grid.Row="1" HorizontalAlignment="Stretch" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*" />
                    <ColumnDefinition Width="2*" />
                </Grid.ColumnDefinitions>
                <TextBox Grid.Column="0" Text="{Binding ItemClass.Property01, Mode=TwoWay}" />
                <Button Grid.Column="1" Command="{Binding RemoveItemCommand}" >
                    <SymbolIcon Symbol="Cancel" />
                </Button>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

А вот список ModelView:

private static ObservableCollection<ItemClass> _MyItemList = new ObservableCollection<ItemClass> {
    new ItemClass{ Property01 = "Sometext" }
};
public ObservableCollection<ItemClass> MyItemList { get { return _MyItemList; } }

И я хочу иметь возможность выполнить следующее (на примере кода из основного представления модели я мог бы создать представление модели элемента при необходимости для решения):

public IMvxCommand RemoveItemCommand { get; private set; }
public MyViewModel(IUserDialogs dialogs)
{
    RemoveItemCommand = new MvxCommand(RemoveItem);
}
public void RemoveItem(object theItem) { MyItemList.Remove(theItem); }

Ответы [ 3 ]

0 голосов
/ 01 мая 2018

Было бы лучше иметь пункт контекстного меню в представлении списка (или кнопку удаления на странице где-нибудь), чтобы удалить выбранные в данный момент элементы. Затем вы можете получить выбор из списка.

В качестве альтернативы вы можете присоединить контекстное меню к элементу представления списка в PrepareContainterForItemOverride (и отсоединить его в другом методе Override)

Это был бы более стандартный стиль взаимодействия.

Если у вас должна быть кнопка внутри элемента представления списка, то самым простым способом получить элемент списка, вероятно, будет использование помощника по визуальному дереву, чтобы перейти от кнопки к элементу представления списка и затем получить фактический элемент. из списка просмотра элемента.

0 голосов
/ 01 мая 2018

Спасибо за все подсказки, Используя ответ Soonts, я смог разработать быстрое решение,

Вот как выглядит окончательная реализация для справки для тех, кто хочет скопировать / вставить / адаптировать (обратите внимание, что я не тестировал код, поскольку заменял имена переменных / функций):

XAML:

<ListView x:Name="ItemClass_ListView" ItemsSource="{Binding MyItemList}" SelectionMode="None" ScrollViewer.VerticalScrollMode="Disabled" ItemContainerTransitions="{x:Null}"> 
    <ListView.ItemTemplate>
        <DataTemplate >
            <Grid Grid.Row="1" HorizontalAlignment="Stretch" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*" />
                    <ColumnDefinition Width="2*" />
                </Grid.ColumnDefinitions>
                <TextBox Grid.Column="0" Text="{Binding ItemClass.Property01, Mode=TwoWay}" />
                <Button Grid.Column="1" Command="{Binding ElementName=ItemClass_ListView, Path=DataContext.RemoveItemCommand}" CommandParameter="{Binding}" >
                    <SymbolIcon Symbol="Cancel" />
                </Button>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

ViewModel:

public class MyViewModel : BaseViewModel, INotifyPropertyChanged
{
    public IMvxCommand RemoveItemCommand { get; private set; }
    public MyViewModel()
    {
        // Initializing Commands
        RemoveItemCommand = new MvxCommand<ItemClass>(OnRemoveItemClick);
    }

    public void OnRemoveItemClick(ItemClass anItem)
    {
        // Do stuff...
    }

    private static ObservableCollection<ItemClass> _MyItemList = new ObservableCollection<ItemClass> {
        new ItemClass(),
        new ItemClass()
    };

    public ObservableCollection<ItemClass> MyItemList
    {
        get { return _MyItemList; }
    }
}
0 голосов
/ 01 мая 2018

Добавьте атрибут x:Name="listView" в свой ListView, затем в шаблон

<Button Grid.Column="1"
    Command="{Binding ElementName=listView, Path=DataContext.RemoveItemCommand}"
    CommandParameter="{Binding}" >

Однако, когда я сталкиваюсь с такими проблемами, я обычно просто использую код позади. Причина в том, что я могу использовать отладчик для кода C # в Visual Studio, но отладка этих сложных привязок намного сложнее. Вот версия C #, код IMO чище, и ее легче отлаживать:

void removeItem_Click( object sender, RoutedEventArgs e )
{
    object i = ((FrameworkElement)sender).DataContext;
    ( this.DataContext as MyViewModel )?.RemoveItem( i );
}

Или, может быть, это только мои личные предпочтения.

...