如何处理其他绑定形式的计算字段?

How to handle calculated fields in otherwise bound forms?

这涉及表单上的批准字段。在数据库中,它是一个 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,但它们似乎过火了,甚至在实际字段值没有更改时也会触发。

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

1 ) 使用计算列

假设:

  • 您有一个强类型数据集,其中包含两个 table 应用程序和用户
  • 您在应用程序中有以下列:Approved(bool)、ApproveDate(datetime)、ApprovedByUserId(int)
  • 您在应用程序和用户之间有一个数据关系,将 Applications.ApprovedByUserId(许多)映射到 User.UserId(一个),并且 UserId 也是一个 int

进程:

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

您已经有一些进程可以将良好的数据填充到 table:

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

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

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

您可以在 DataColumn.Expression

中详细了解可以使用的语法

如果您没有批准布尔值,您可以添加一个或使用其他测试,例如 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
  2. 上绑定不同的东西

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

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

您可以将它们的每一个 Visible 属性绑定到 Approved 布尔值,以便在用户导航到未批准的行时标签消失。

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

还有其他方法,涉及绑定到数据关系的多个绑定源。我们甚至可以轻摇组合框来完成它 - 组合有用户的数据源 table,但数据成员为“来自应用程序 table 的 ApprovedByUserId”;它将执行 ApprovedByUserId <--> UserId 等价

的 2 种方式查找