首页 > 解决方案 > 如何处理其他绑定表单中的计算字段?

问题描述

这涉及表单上的批准字段。在数据库中,它是一个 bool 字段、一个包含对批准者的 FK 的 int 字段,以及一个日期时间字段,它们一起指示某项内容是否已获得批准,如果是,则由谁批准以及何时批准。在表格上,这必须翻译成“John Smith 于 01/02/03 04:05 批准”之类的内容。

我用导航栏处理这个问题。当绑定源位置发生变化时,事件被捕获并且代码格式化计算字段,就像这样(代码做了什么并不那么重要)。

private void ctlNavBar1_displayCurrent(object sender, EventArgs e)
{
    var drv = talsBindingSource.Current as DataRowView;
    if (drv != null)
    {
        ctlBoundCheckButton1.lblText = $"Submitted {drv.Row.Field<DateTime>("SubmitDate").ToString("MM/dd/yy hh:mm tt")}";
        ctlBoundCheckButton1.setControls(true);
        if (drv.Row.Field<bool>("Approved"))
        {
            var sup = talsSupervisorsBindingSource.Current as DataRowView;
            ctlBoundCheckButton2.lblText = $"Approved by {sup.Row.Field<string>("FullName")} on {drv.Row.Field<DateTime>("ApproveDate").ToString("MM/dd/yy")}";
            ctlBoundCheckButton2.setControls(true);
        }
    }
    else
    {
        using (DialogCenteringService centeringService = new DialogCenteringService(this))
        {
            MessageBox.Show("No TALs to Approve", "Confirm", MessageBoxButtons.OK);
        }
        Close();
    }
}

问题是

public TALsApprove()
{
    InitializeComponent();
    talsTableAdapter.FillForApproval(timeTrackDataSet.TALs, User.ID);
    usersTableAdapter.FillBySupervisor(timeTrackDataSet.Users, User.ID);
    timeSlipsTableAdapter.FillBySupervisor(timeTrackDataSet.TimeSlips, User.ID);
    ctlNavBar1.displayCurrent += ctlNavBar1_displayCurrent;
    ctlNavBar1.bindingSource = talsBindingSource;
    // this assignment doesn't fire Position Changed (or anything else, as far as I can tell)
}

首次分配绑定源时,绑定源事件 PositionChanged 不会触发。我已经通过使用表单 Shown 事件解决了这个问题,就像这样。

private void TALsApprove_Shown(object sender, EventArgs e)
{
    ctlNavBar1_displayCurrent(null, new EventArgs());
}

所以我的问题是:

1.- 像这样直接调用事件处理程序是否会与 .NET 的任何内部结构混淆?(例如内存泄漏、堆栈问题等)

2.- 在首次初始化绑定源以及当前记录的内容发生变化时,是否有一种不那么笨拙的方式来处理字段的计算?我尝试了绑定源事件 CurrentChanged 和 CurrentItemChanged,但它们似乎过火了,即使没有实际字段值发生更改也会触发。

标签: c#winforms

解决方案


我可能会想到几种方法来整理它:

1 ) 使用计算列

假设:

  • 您有一个强类型数据集,其中包含两个表,例如 Applications 和 Users
  • 您在 Applications 中有以下列: Approved(bool)、ApproveDate(datetime)、ApprovedByUserId(int)
  • 您在 Applications 和 Users 之间有一个单一的数据关系,将 Applications.ApprovedByUserId (many) 映射到 User.UserId (one),并且 UserId 也是一个 int

过程:

  • 在您的数据集中单击 Applications 表,然后添加一个字符串列
  • 将其 Expression 属性设置为:IIF([Approved] = False,'Not approved','Approved by' + Parent.Username + ' on ' + [ApproveDate])

在此处输入图像描述

您已经有一些将好的数据填充到表中的过程:

在此处输入图像描述

当您运行应用程序时,构建叙述成为数据表的问题:

在此处输入图像描述

让我们在运行时编辑另一个细节:

在此处输入图像描述

当您完成编辑并移出该行时,它将被提交到表格并且叙述会自动更新

您可以阅读有关可以在DataColumn.Expression中使用的语法的更多信息

如果您没有批准 bool,则可以添加一个或使用其他一些测试,例如IIF(ApprovedByUserId IS NULL,'Not Appproved,'App...'). If yo uhave multiple datarelations coming off Applications you specify the name of the relation after Parent like Parent(App_User).UserName`,假设数据关系称为 App_User


  1. 在 UI 上绑定不同的东西

没有人说过你只需要绑定文本。如果您的数据集中有一个“已批准”布尔列,则可以连续有多个标签:

--label1----- --label2------ --label3-- --label4--
"Approved by" BindParentName " on "     BindDate

您可以将它们的每个 Visible 属性绑定到 Approved 布尔值,这样如果用户导航到未经批准的行,标签就会消失。

将父用户名放入 Applications 数据表中的最简单方法(因为所有这些标签都绑定到 Applications 表上的 indingsource,对吗?)是Expression在上面的新列上使用 an,但更简单(只是Parent.UserName或Parent(App_User).UserName`) 将用户名导入应用程序数据表。

还有其他方法,涉及绑定到数据关系的多个绑定源。我们甚至可以摇动一个组合框来执行此操作 - 该组合具有用户表的 DataSource,但应用程序表中的“ApprovedByUserId”的 DataMember;它将执行ApprovedByUserId <--> UserId等价的 2 路查找


推荐阅读