如何将内联动作按钮(Inline Action Buttons)添加到网格?

本节的 TypeScript 版本有待更新

你可以在网络添加一些内联动作图标,用以删除当前行、打开对话框、调用服务等。

让我们在客户网格列表(CustomersGrid)添加一个含删除按钮的新列。

首先从 CustomerGrid 删除 IAsyncInit 接口,否则你得重写 GetColumnsAsync。

  1. namespace Serene.Northwind
  2. {
  3. //...
  4. public class CustomerGrid : EntityGrid<CustomerRow>
  5. {
  6. public CustomerGrid(jQueryObject container)
  7. : base(container)
  8. {
  9. }
  10. //...
  11. protected override List<SlickColumn> GetColumns()
  12. {
  13. var columns = base.GetColumns();
  14. columns.Add(new SlickColumn
  15. {
  16. Field = "DeleteRow",
  17. Title = "",
  18. Format = ctx =>
  19. {
  20. return "<a class='inline-action delete-row' title='delete'></a>";
  21. },
  22. Width = 24,
  23. MinWidth = 24,
  24. MaxWidth = 24
  25. });
  26. return columns;
  27. }
  28. }
  29. }

现在我们需要给我们的按钮添加样式。在 site.less 末尾添加下面的样式:

  1. .inline-action {
  2. background-repeat: no-repeat;
  3. background-position: center center;
  4. width: 16px;
  5. height: 16px;
  6. cursor: pointer;
  7. opacity: 0.5;
  8. display: inline-block;
  9. &:hover {
  10. opacity: 1;
  11. }
  12. }
  13. .delete-row {
  14. background-image: url(../serenity/images/delete2.png);
  15. }

我用基本 CSS 类 inline-action 来设置默认按钮的样式。通过这种方式,你可以只改变 delete-row 类并设置其 background-image 创建不同的动作按钮。

生成并运行项目后,在客户网格列表最右边,我们将有一个删除连接。当你点击该连接,不会有任何响应,因为我们还没有处理该点击的事件。下面我们来添加该点击事件:

  1. protected override void OnClick(jQueryEvent e, int row, int cell)
  2. {
  3. base.OnClick(e, row, cell);
  4. if (e.IsDefaultPrevented())
  5. return;
  6. var item = Items[row];
  7. if (J(e.Target).HasClass("inline-action"))
  8. {
  9. e.PreventDefault();
  10. if (J(e.Target).HasClass("delete-row"))
  11. {
  12. Q.Confirm("Delete record?", () =>
  13. {
  14. CustomerService.Delete(new DeleteRequest
  15. {
  16. EntityId = item.ID.Value
  17. }, onSuccess: response =>
  18. {
  19. Refresh();
  20. });
  21. });
  22. }
  23. }
  24. }

我们首先检查点击事件是否被基本的网格类处理,来防止同样的事件被处理再次。例如,基本的网格类在 customer ID 和 name 处理了编辑连接。

然后,我们获得点击行的实体。

下一步骤是检查单击的 HTML 元素是否有 inline-action 样式,如果有该样式,我们就阻止其默认行为。

然后,我们检查单击元素是否是 delete-row 操作,如果是该操作,则弹出确认框给用户确认。 Q.Confirm 在第二个参数中指定用户确认操作后所调用的操作。

如果用户确认了删除操作,我们调用 CustomerService.Delete 方法删除所选的行,并使用删除成功之后的回调方法刷新网格。

让我们添加另一个操作来编辑客户(你可以用相同的方法打开另一对话框)。

  1. protected override List<SlickColumn> GetColumns()
  2. {
  3. var columns = base.GetColumns();
  4. columns.Add(new SlickColumn
  5. {
  6. Field = "DeleteRow",
  7. Title = "",
  8. Format = ctx =>
  9. {
  10. return "<a class='inline-action delete-row' title='delete'></a>";
  11. },
  12. Width = 24,
  13. MinWidth = 24,
  14. MaxWidth = 24
  15. });
  16. columns.Add(new SlickColumn
  17. {
  18. Field = "EditRow",
  19. Title = "",
  20. Format = ctx =>
  21. {
  22. return "<a class='inline-action edit-row' title='edit customer'></a>";
  23. },
  24. Width = 24,
  25. MinWidth = 24,
  26. MaxWidth = 24
  27. });
  28. return columns;
  29. }

为其添加 CSS:

  1. .delete-row {
  2. background-image: url(../serenity/images/delete2.png);
  3. }
  4. .edit-row {
  5. background-image: url(../serenity/images/magnifier.png);
  6. }

添加单击处理事件:

  1. protected override void OnClick(jQueryEvent e, int row, int cell)
  2. {
  3. base.OnClick(e, row, cell);
  4. if (e.IsDefaultPrevented())
  5. return;
  6. var item = Items[row];
  7. if (J(e.Target).HasClass("inline-action"))
  8. {
  9. e.PreventDefault();
  10. if (J(e.Target).HasClass("delete-row"))
  11. {
  12. Q.Confirm("Delete record?", () =>
  13. {
  14. CustomerService.Delete(new DeleteRequest
  15. {
  16. EntityId = item.ID.Value
  17. }, onSuccess: response =>
  18. {
  19. Refresh();
  20. });
  21. });
  22. }
  23. else if (J(e.Target).HasClass("edit-row"))
  24. {
  25. var dlg = new CustomerDialog();
  26. InitEntityDialog(dlg);
  27. dlg.LoadByIdAndOpenDialog(item.ID.Value);
  28. }
  29. }
  30. }

我们首先创建一个新的客户对话框。 InitEntityDialog 是 CustomerGrid 的一个方法,它允许附加 ondatachange 事件,因此当对话框的数据改变时,它可以自动刷新。然后,我们调用 LoadByIdAndOpenDialog 加载所选 ID 的客户到对话框,在加载完成后显示对话框。