我以编程方式将一个delete按钮列添加到我的datagridview中,它工作得很好。但是,当我将datagridview设置为一个新的数据源时,CellClick函数在打印0而不是6的情况下不再工作,6是正确的值。
//prints out 6
    private void DataGridView_PromoList_CellClick(object sender, DataGridViewCellEventArgs e)
    {
        Console.WriteLine(DataGridView_PromoList.Columns["dataGridViewDeleteButton"].Index);
    }
    // above function prints out 0 after this functions called
    private void cmbbxFilter_SelectedIndexChanged(object sender, EventArgs e)
    {
        //probably don't need this try catch because not reloading database
        try {
            int index = cmbbxFilter.SelectedIndex;
            // Only do something if selecting different index in filter
            if (lastFilterIndex != index)
            {
                lastFilterIndex = index;
                etp.loadDisplayDT(index);
                DataGridView_PromoList.DataSource = etp.displayDT;
                Console.WriteLine("REFRESHED!");
            }
        }
        catch (Exception ex)
        {
            showAlertUser("ERROR: " + ex.Message.ToString(), false);
            //.Windows.Forms.Application.Exit();
        }
    }发布于 2021-05-20 02:56:45
我不确定为每一行添加一个删除按钮是否明智。考虑在“删除”列中给每一行一个复选框,并使用一个“Save”按钮(或“OK”,“Apply Now”)启动对所有选中项的删除操作。
将此界面与编辑文本文件进行比较:只要操作员没有选择Save,他就可以进行更改。如果他不想让更改生效,只需不按Ok即可。
因此,如果操作员犯了错误,该项目不会立即删除。他可以撤销点击。
为此,您需要将DataGridviewButtonColumn更改为DataGridViewCheckBoxColumn。
如果想要显示一系列Customers,则必须创建一个DisplayedCustomers类,该类聚合了Customers并具有额外的列IsDeleted
class Customer {...}
class DisplayedCustomer
{
    public Customer Customer {get; set;}
    // Do readonly like this:
    public int Id => this.Customer.Id;
    // changeable properties like this:
    public string Name
    {
        get => this.Customer.Name;
        set => this.Customer.Name = value;
    }
    ... // other properties
    // Add: IsDeleted
    public bool IsDeleted {get; set;}
}您已经在使用DataSource来显示您的客户(或您所显示的任何内容)。使用visual studio设计器或手动更改代码,如下所示:
public MyForm()
{
    InitializeComponents();
    this.columnId.DataPropertyName = nameof(DisplayedCustomer.Id);
    this.columnName.DataProperyName = nameof(DisplayedCustomer.Name);
    ...
    this.columnIsDeleted.DataPropertyName = nameof(DisplayedCustomer.IsDeleted);
}
public BindingList<DisplayedCustomer> DisplayedCustomers()
{
    get => (BindingList<DisplayedCustomer>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;
}
public void InitCustomerDisplay()
{
    IEnumerable<Customer> customers = this.FetchCustomersToDisplay(...);
    IEnumerable<DisplayedCustomer> customersToDisplay = customers
        .Select(customer => new DisplayedCustomer {Customer = customer});
    this.DisplayedCustomers = new BindingList<DisplayedCustomer>(
        customersToDisplay.ToList());
}所有客户都会显示出来,还有一个额外的列IsDeleted。操作员所做的任何更改都会在客户中自动更新,但属性IsDeleted除外。
当操作员单击Ok或Apply Now时删除客户
private void OnButtonApplyNow_Clicked(object sender, ...)
{
    IEnumerable<Customer> customersToDelete = this.DisplayedCustomers
        .Where(displayedCustomer => displayedCustomer.IsDeleted)
        .Select(displayedCustomer => displayedCustomer.Customer);
    this.DeleteCustomers(customersToDelete);
}还有改进的空间
考虑将IsDeleted作为列添加到数据库表中。调整您的存储库,以便对于大多数用户,它只获取未删除的客户。
更改存储库属性:
public IQueryable<Customer> Customers => dbContext.Customers;进入:
public IQueryable<Customer> Customers => dbContext.Customers
    .Where(customer => !customer.IsDeleted);这样,每当有人意外删除某个项目时,该项目并未真正删除,他可以向超级用户发送电子邮件,并要求取消删除该项目。当然,超级用户与数据库的接口略有不同。
定期地,例如每月一次,将启动一个额外的进程来删除不久前删除的所有项目。为此,拥有一个可以为空的DeleteDate列可能会更好:如果为null,则不为IsDeleted,如果不为null,则额外的进程可以使用值To来仅删除半年前删除的项。
https://stackoverflow.com/questions/67375110
复制相似问题