UWP - MVVM - 使用 ItemTemplate 按钮删除 ListView 项目

UWP - MVVM - Remove ListView item using ItemTemplate button

我有一个显示项目列表的屏幕,用户可以点击按钮从列表中删除相应的项目。

我正在尝试使用 MVVM 这样做。

但是项目在执行操作时并不知道包含列表。 我在这里和那里看到了一些答案,但是 none 他们使用我环境中开箱即用的 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>

这是模型视图列表:

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); }

x:Name="listView" 属性添加到您的 ListView,然后在模板中

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

但是,当我遇到这样的问题时,我通常只是使用代码隐藏。原因是,我可以在 visual studio 中使用 C# 代码的调试器,但调试这些复杂的绑定要困难得多。这是一个 C# 版本,代码更清晰,更易于调试:

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

或许这只是我个人的喜好。

最好在列表视图上有一个上下文菜单项(或页面某处的删除按钮)以删除当前选定的项目。然后您可以从列表视图中获取选择。

或者,您可以将上下文菜单附加到 PrepareContainterForItemOverride 中的列表视图项(并在其他 Override 方法中将其分离)

那将是一种更标准的交互方式。

如果您必须在列表视图项中包含按钮,那么获取列表项的最简单方法可能是使用可视化树助手从按钮向上移动到列表视图项,然后获取列表视图项目中的实际项目。

感谢所有提示, 使用 Soonts 答案,我能够开发出一个快速的解决方案,

这是最终实现的样子,供任何想要的人参考 copy/paste/adapt(注意我没有测试代码,因为我替换了 variables/functions 名称):

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>

视图模型:

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; }
    }
}