如何从 Xamrin.Form 中的 ListView 和 ViewModel ObservableRangeCollection 中删除项目?

How to delete item from ListView and ViewModel ObservableRangeCollection in Xamrin.Form?

我想从 Xamrin.Form 中的 ListView 和 ViewModel ObservableRangeCollection 中删除项目。

员工结果页面

<ListView x:Name="EmployeeResultsListView"
          ItemsSource="{Binding EmployeeResults}"
          RowHeight="200"
          IsPullToRefreshEnabled="true"
          RefreshCommand="{Binding RefreshDataCommand}"
          IsRefreshing="{Binding IsRefreshingData, Mode=OneWay}"
          ItemAppearing="Employee_ItemAppearing"
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:EmployeeResultViewCell />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

EmployeeResultViewModel

[ImplementPropertyChanged]
public class EmployeeResultsViewModel : ViewModelBase
{
    private async Task LoadEmployee()
    {
        EmployeeResults = GetDataUsingAPI(); //15 records per call
        OnDeleteEmployeeCommand = new RelayCommand<object>(async (model) => await DeleteEmployee(model));
    }

    public ObservableRangeCollection<ExtendedEmployee> EmployeeResults { get; set; }

    public string EmployeePhotoUrl { get; set; }
    public string EmployeeName { get; set; }
    public ICommand OnDeleteMessageCommand { get; set; }
    private async Task DeleteEmployee(object obj)
    {
        //get object here
    }
}

EmployeeResultViewCell

<ViewCell.ContextActions>
    <MenuItem
        Text="Delete"
        IsDestructive="true"
        Command="{Binding Path=BindingContext.OnDeleteEmployeeCommand, Source={x:Reference EmployeeResultsPage}}"
        CommandParameter="{Binding .}"/>
</ViewCell.ContextActions>
<ViewCell.View>
    <Grid RowSpacing="0" ColumnSpacing="0" VerticalOptions="Center" HeightRequest="150">
        <Image x:Name="EmployeeImage" Grid.Column="0" HeightRequest="150" WidthRequest="150"
        Source="{Binding EmployeePhotoUrl}" />
        <Label Text="{Binding EmployeeName}" FontSize="18" TextColor="Grey"/>
    </Grid>
</ViewCell.View>

CS 文件

public partial class EmployeeResultViewCell : CustomViewCell
{
    public EmployeeResultViewCell()
    {
        InitializeComponent();
    }

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();
        var employee = (BindingContext as ExtendedEmployee);
    }

}

更改:删除点击事件并添加绑定。

对于 MVVM,您不是在使用事件,而是在您的视图模型中使用可以绑定到视图命令的命令。实现你想要的最 MVVM 方法是添加一个 ICommand 可绑定 属性 到你的单元格

public partial class EmployeeResultViewCell : CustomViewCell
{
    /// <summary>
    ///   The <see cref="DeleteCommand" /> bindable property.
    /// </summary>
    public static readonly BindableProperty DeleteCommandProperty = BindableProperty.Create(nameof(SealCheckListPage.DeleteCommand), typeof(ICommand), typeof(SealCheckListPage), default(ICommand));

    /// <summary>
    ///   Gets or sets the DeleteCommand that is called when we'd like to delete an employee.
    /// </summary>
    public ICommand DeleteCommand
    {
        get => (ICommand)this.GetValue(SealCheckListPage.DeleteCommandProperty);

        set => this.SetValue(SealCheckListPage.DeleteCommandProperty, value);
    }

    private void MenuItemDelete_Clicked(object sender, System.EventArgs e)
    {
        DeleteCommand?.Execute(BindingContext);
    }
}

现在您可以将 DeleteCommand 绑定到您的视图模型

<ListView>
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:EmployeeResultViewCell DeleteCommand="{Binding BindingContext.DeleteCommand, Source={x:Reference Page}}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

请注意,包含 ListView 的页面必须具有 x:Name="Page" 才能正确绑定命令。不可否认,以这种方式绑定命令并不是真正的最佳选择,但据我所知这是我们能做的最好的,MVVM-wise.

您要做的最后一件事是将 ICommand 属性 添加到您的视图模型

public class EmployeeResultsViewModel : ViewModelBase
{
    private async Task LoadEmployee()
    {
        EmployeeResults = GetDataUsingAPI(); //15 records per call

        DeleteCommand = new Command<ExtendedEmployee>(OnDelete);
    }

    public ICommand DeleteCommand { get; }

    private void OnDelete(ExtendedEmployee employee)
    {
        // delete the employee from the collection
    }

    /* ... */
}

现在,当您的单元接收到事件时,它会执行绑定到视图模型中的命令的命令。执行此命令时,它会执行传递的委托 OnDelete,您可以在其中访问要从中删除 ExtendedEmployee 的集合。