繁体   English   中英

如何使用按钮软删除 DataGrid 视图中的选定行

[英]How to soft delete a selected row in a DataGrid View using a button

所以我有一个名为 MyMovieDataDrid 的 DataGridView,它连接到一个 sql 服务器,我已经有我的 IsDeleted 属性和一个如下所示的删除存储库,顺便说一下,我的 IsDeleted 属性自动显示为一个复选框,所以如果复选框被选中这是真的,如果不是它是假的

public bool DeleteMovie(Guid id)
{
       bool isDeleted = false;
       var movie =  _context.Movie.FirstOrDefault(m => m.Id == id);
       if (movie != null)
       {
            movie.IsDeleted = true;
            _context.SaveChanges();
            isDeleted = true;
       
       } 
        return isDeleted;
}

这是我的删除按钮方法,所以当我按下它时,它会运行我的逻辑并从 DataGridView 中软删除一行我尝试了多种解决方案,例如使用选定的行事件处理程序来获取选定的行,然后运行存储库方法但没有到目前为止已经工作了。

    private void DeleteButton_Click(object sender, EventArgs e)
    {
        Movie movie = new Movie();
        
        if(MyMovieDataGrid.SelectedRow.Count > 0)
        {
          _movieRepo.DeleteMovie(movie.Id);
        }
    }

和我所有的财产

    Movie movie = new Movie()
    {
        Id = Guid.NewGuid(),
        IsDeleted = false,
        MovieNames = MovieNameBox.Text;
     
    }
         

和我的 AddMovie 存储库

    public void AddMovie(Movie movie)
    {
        _context.Movie.Add(movie);
        _context.SaveChanges();

    }
      

电影存储方法

    private NRIDataContext _context;    
    public MovieRepository()
    {
        _context = new NRIDataContext();    
    }
       
     //GetMovie repository
     
   GetMovie() 
   {
            
    
    
        var movies = _context.Movie.Where(m => m.IsDeleted 
        ==false).ToList();
        return  movie;
                                                                                                                                                                                     
   }
      
     MyMovieDataGrid.DataSource = _movieRepo.GetMovie().OrderByDescending(x => x.MovieNames.First) .ToList();
  
     

所以我的问题是如何让我的 Datagrid 知道何时运行我的存储库方法,我觉得我必须以某种方式编写一些代码,如果 IsDeleted 属性为真,它会选择整行然后我运行我的 DeleteMovie 方法但没有解决方案已经奏效。

考虑在OnModelCreating中设置一个过滤器,在这种情况下,我使用了一个名为Contact1的模型,因为我已经有了它。 在基础表中添加IsDeleted列,但不在模型中。

下面显示了软删除行并将其从 DataGridView 中删除的基础知识。 没有适当的存储库。

public partial class Contact1 : INotifyPropertyChanged
{
    private int _contactId;
    private string _firstName;
    private string _lastName;

    public int ContactId
    {
        get => _contactId;
        set
        {
            _contactId = value;
            OnPropertyChanged();
        }
    }

    public string FirstName
    {
        get => _firstName;
        set
        {
            _firstName = value;
            OnPropertyChanged();
        }
    }

    public string LastName
    {
        get => _lastName;
        set
        {
            _lastName = value;
            OnPropertyChanged();
        }
    }

    public Contact1()
    {
        
    }

    public override string ToString() => $"{FirstName} {LastName}";

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

OnModelCreating

modelBuilder.Entity<Contact1>()
    .HasQueryFilter(contact =>
        EF.Property<bool>(contact, "isDeleted") == false);

然后override SaveChanges

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new ())
{
    DoShadowyStuff();
    return base.SaveChangesAsync(cancellationToken);
}

public override int SaveChanges()
{
    DoShadowyStuff();

    return base.SaveChanges();
}

然后在DoShadowlyStuff中,如果状态为 Deleted,则将状态设置为 modified。

private void DoShadowyStuff()
{
    ChangeTracker.DetectChanges();

    foreach (var entry in ChangeTracker.Entries())
    {

        if (entry.State == EntityState.Deleted)
        {
            // Change state to modified and set delete flag
            entry.State = EntityState.Modified;
            entry.Property("isDeleted").CurrentValue = true;
        }
    }
}

非常基本的readdelete操作

public class Operations
{
    public static void Remove(Contact1 contact1)
    {
        using (var context = new ShadowContext())
        {
            context.Add(contact1).State = EntityState.Deleted;
            context.SaveChanges();
        }
    }

    public static List<Contact1> Contacts()
    {
        using (var context = new ShadowContext())
        {
            return context.Contacts1.ToList();
        }
    }
}

基本的表单操作。 单击删除按钮,将当前行的状态设置为已删除,保存将联系人标记为已修改的更改并设置 isDeleted。 接下来从 BindingList 中删除删除,然后从 DataGridView 中删除该行。

public partial class Form1 : Form
{
    private BindingList<Contact1> _bindingList;
    private readonly BindingSource _bindingSource = new ();
    public Form1()
    {
        InitializeComponent();
        Shown += OnShown;
    }

    private void OnShown(object sender, EventArgs e)
    {
        _bindingList = new BindingList<Contact1>(Operations.Contacts());
        _bindingSource.DataSource = _bindingList;
        dataGridView1.DataSource = _bindingSource;
    }

    private void DeleteButton_Click(object sender, EventArgs e)
    {
        Operations.Remove(_bindingList[_bindingSource.Position]);
        _bindingList.RemoveAt(_bindingSource.Position);
    }
}

在此处输入图像描述

我喜欢 Karen 的方法,因为它更像是“应该如何完成”,但这与您编写的内容相去甚远,我怀疑您可能不想大规模更改当前代码

您的方法的基本问题是您没有从单击的行中获取电影 ID,您制作了一部新电影,该电影具有一个新的随机 Guid,据说它根本不会在数据库中,因为 Guid 不太可能重复,然后你尝试删除它:

private void DeleteButton_Click(object sender, EventArgs e)
{
    //make a new movie with random id 
    Movie movie = new Movie();
    
    if(MyMovieDataGrid)
    {
        //delete the new random id
        _movieRepo.DeleteMovie(movie.Id);
    }
}

这意味着您要删除的电影实际被删除的几率是惊人的 5316911983139663491615228241121400000 到 1; 如果您现在开始点击并继续前进,直到地球被太阳吞噬红巨星,这可能不会发生😀

从单击的行中检索要删除的 Guid; 添加一个 CellContentClicked 处理程序并检查它是被单击的已删除按钮列,然后将电影 id 从行的数据绑定项中拉出:

private void DGV_CellContentClick(object sender, 
DataGridViewCellEventArgs e)
{
    //don't process clicks on the header row 
    if(e.RowIndex < 0) return;

    //don't process clicks on columns other than delete
    if(e.ColumnIndex != MyMovieDataGrid.Columns["nameOfYourDeleteColumn"].ColumnIndex) return;

    
    //pull the movie from that row
    Movie movie = MyMovieDataGrid.Rows[e.RowIndex].DataBoundItem as Movie;
    
    if(MyMovieDataGrid) //I don't know what this means; a DataGridView is not a boolean
    {
        //delete the movie id
        _movieRepo.DeleteMovie(movie.Id);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM