我需要代表这样做吗?

时间:2016-01-14 03:39:21

标签: c# delegates

我有一个应用程序,其中有许多DataGridViews,它显示来自多个类实例的信息。该类有各种属性,每个都有一个DataGridView。

简单来说,我希望用户能够更新DataGridView中的值,然后拥有一个获取该数据并更新该类的例程。

我可以相当轻松地做到这一点,但我认为必须有一种更简洁的方式来做到这一点,我只是不够聪明才能找到自己!

我目前的工作方式是,我有一个以与其中一个属性关联的DataGridView开始的函数,处理数据以专门更新该属性。然后我对下一个DataGridView做同样的事情,依此类推。每个DataGridView的代码几乎完全相同,除了更新的属性的名称,以及类型转换,以确保DataGridViewCell内容转换为属性的正确类型(Double和Int)。

现在:我花了很多时间尝试研究一种更简洁的方法:代理,包含抽象方法的类,泛型。问题是我不确切知道要搜索什么,但我认为最好的选择是使用Lambda指向要更新的属性的某种委托,以及对该属性的类型检查。不幸的是,我不知道该怎么做,所以我甚至不能开始为它编写代码!

这是我所拥有的基本前提:

//Update Priorities
if (_PrioritiesGrid != null)
{
    for (int i = 0; i < _PrioritiesGrid.Rows.Count - 1; i++)        //Ignore last row - it is blank for user added rows.
    {
        DataGridViewRow priorityRow = _PrioritiesGrid.Rows[i];
        DateTime productionDay = Convert.ToDateTime(priorityRow.Cells[0].Value);
        if (!storedDates.Contains(productionDay)) storedDates.Add(productionDay);
        for (int j = 1; j < priorityRow.Cells.Count; j++)
        {
            Well well = (Well)_PrioritiesGrid.Columns[j].Tag;
            if (_WellList.ContainsValue(well))
            {
                well.SetPriority(productionDay, Convert.ToInt32(priorityRow.Cells[j].Value));
            }
        }
    }
}

//Update Potentials
if (_PotentialsGrid != null)
{
    for (int i = 0; i < _PotentialsGrid.Rows.Count - 1; i++)        //Ignore last row - it is blank for user added rows.
    {
        DataGridViewRow potentialsRow = _PotentialsGrid.Rows[i];
        DateTime productionDay = Convert.ToDateTime(potentialsRow.Cells[0].Value);
        if (!storedDates.Contains(productionDay)) storedDates.Add(productionDay);
        for (int j = 1; j < potentialsRow.Cells.Count; j++)
        {
            Well well = (Well)_PotentialsGrid.Columns[j].Tag;
            if (_WellList.ContainsValue(well))
            {
                well.SetPotential(productionDay, Convert.ToDouble(potentialsRow.Cells[j].Value));
            }
        }
    }
}

Well.SetPotential()使用_PotentialsGrid中的数据填充Well类的实例; Well.SetPriority()使用_PrioritiesGrid中的Data填充Well Class的实例。

我正在设想某种委托功能,这意味着我可以去:

ProcessGrid(_PotentialsGrid, x=>x.SetPotentials()) and
ProcessGrid(_PrioritiesGrid, x=>x.SetPriorities()) 

SetPotentials和SetPriorities都采用参数(我在实际开始阅读网格数据时才会得到)这一事实是一个额外的复杂因素!

如果有人能指出我正确的方向,那就太好了。

1 个答案:

答案 0 :(得分:1)

我认为与代表们合作是一个好主意。 请根据控制反转为此创建解决方案(或框架)。

在较高级别,您的功能(或框架功能)应该采用两个输入 -

  1. DataGridView(或更好的抽象) - 因此您应该能够指定要跟踪的更新哪些单元格。
  2. 委托 - 当指定单元格的值发生变化时,这将是一个需要调用的Action。 要读取哪些单元格以及如何处理读取值将成为委托的一部分。
  3. 现在,每当单元格的值发生变化时,框架都有责任调用您传递的委托(从而反转控制权)。 代表知道要读取哪些单元格&amp;如何处理读取值。

    如果有任何不清楚的地方或者您想要某种工作代码,请给我发表评论。

    更新1。了解代表的示例用法是必需的。提供示例代码

    我根据您的需要ProcessGrid

    将代码放在一个函数中
    public void ProcessGrid(DataGridView gridView, Action<Well, DateTime, DataGridViewCell> operaiton)
            {
                if (gridView != null)
                {
                    for (int i = 0; i < gridView.Rows.Count - 1; i++)        //Ignore last row - it is blank for user added rows.
                    {
                        DataGridViewRow priorityRow = gridView.Rows[i];
                        DateTime productionDay = Convert.ToDateTime(priorityRow.Cells[0].Value);
                         if (!storedDates.Contains(productionDay)) storedDates.Add(productionDay);
                        for (int j = 1; j < priorityRow.Cells.Count; j++)
                        {
                            Well well = (Well)gridView.Columns[j].Tag;
                              if (_WellList.ContainsValue(well))
                            {
                               // This is where the delegate will fire.
                                operaiton(well, productionDay, priorityRow.Cells[j]);
                            }
                        }
                    }
                }
            }
    

    这就是你可以调用这个ProcessGrid功能的方法。

    ProcessGrid(_PrioritiesGrid, (well, productionDay, cell) => { well.SetPriority(productionDay, Convert.ToInt32(cell.Value));});
    
    ProcessGrid(_PotentialsGrid, (well, productionDay, cell) => { well.SetPotential(productionDay, Convert.ToDouble(cell.Value));});
    

    我没有执行它,但我乐观地认为它会正常工作。如果您有任何问题或任何部分不清楚,请写信给我。