繁体   English   中英

datagridview.Columns[""].Index 在设置新数据源后不起作用

[英]datagridview.Columns[""].Index doesn't work after setting new datasource

我以编程方式向我的 datagridview 添加了一个删除按钮列,它工作正常。 但是,当我将 datagridview 设置为新的数据源时,CellClick function 在打印出 0 而不是正确值的 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();
        }
    }

我不确定在每一行添加一个删除按钮是否明智。 考虑在“删除”列中为每一行提供一个复选框,以及一个Save按钮(或确定,立即应用)以启动所有选中项目的删除操作。

将此界面与编辑文本文件进行比较:只要操作员没有选择Save ,他就可以进行更改。 如果他不想使更改生效,请不要按确定。

因此,如果操作员犯了错误,该项目不会立即删除。 他可以撤消点击。

为此,您需要将 DataGridviewButtonColumn 更改为DataGridViewCheckBoxColumn

如果要显示Customers序列,则必须创建一个 class 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 Designer 或手动将代码更改为类似于以下内容:

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 除外。

当操作员单击OkApply 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,则额外进程可以使用该值仅删除半年前删除的项目。

暂无
暂无

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

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