【问题标题】:New button for Foreign Key fields in Dynamic Data动态数据中外键字段的新按钮
【发布时间】:2009-10-25 22:40:06
【问题描述】:

在 ASP.NET 动态数据中的脚手架页面中,如果实体有外键字段,并且您要查找的值不在主键表中,即不在下拉列表中,则必须放弃您对实体的编辑,将寻找的外键值添加到其表中,然后返回到您的原始实体。

我怎样才能在外键字段模板中添加一个“新建”链接/按钮,这将打开一个新窗口(使面板可见),您可以在其中添加所需的值,然后刷新下拉列表?

【问题讨论】:

  • 我知道它不能回答你的问题,但就个人而言,听起来你需要一个输入向导,而不是完全依赖 DyDa。

标签: asp.net dynamic-data


【解决方案1】:

你的意思就像在 django admin ui 中一样;)。 我目前正在尝试实现该功能,如果可以使用,我会在此处发布代码。

编辑:

好的,我明白了,完整的 django 风格......解释起来有点长,但实际上很简单。

要创建的文件:

一个 admin_popup.master 有一个漂亮的弹出页面(复制没有标题的 admin.master)。

以 admin_popup.master 作为主控的 popup_Insert.aspx。 (复制Insert.aspx)

修改

致您的 admin.master.cs: 添加这个:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "refresh_fks", @"
    var fk_dropdown_id;
    function refresh() {
        __doPostBack(fk_dropdown_id,'refresh');
    };", true);
}

在您的 admin_popup.master 中,将这些属性添加到 body 标记(用于调整 poup 的大小)

<body style="display: inline-block;" onload="javascript:resizeWindow();">

在您的 admin_popup.master.cs 中

protected override void  OnInit(EventArgs e)
{
    base.OnInit(e);

    System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "refresh_fks", @"
    var fk_dropdown_id;
    function refresh() {
        __doPostBack(fk_dropdown_id,'refresh');
    };", true);

    System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "resize_window", @"function resizeWindow() {
        window.resizeTo(document.body.clientWidth + 20, document.body.clientHeight + 40);
        window.innerHeight = document.body.clientHeight + 5;
        window.innerWidth = document.body.clientWidth;
    }", true);

    System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "update_parent", @"function updateParent() {
        window.opener.refresh();
    }", true);        
}

在popup_Insert.aspx.cs中,替换这两个函数:

protected void DetailsView1_ItemCommand(object sender, DetailsViewCommandEventArgs e) {
    if (e.CommandName == DataControlCommands.CancelCommandName)
        System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Close_Window", "self.close();", true); 
}

protected void DetailsView1_ItemInserted(object sender, DetailsViewInsertedEventArgs e) {
    if (e.Exception == null || e.ExceptionHandled) {
        System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Close_Window", "window.opener.refresh(); self.close();", true); 
    }
}

在 ForeignKey_Edit.ascx 中,添加一个 LinkBut​​ton (ID=LinkBut​​ton1) 并在 ForeignKey_Edit.ascx.cs 中,替换该函数

protected void Page_Load(object sender, EventArgs e) {
    if (DropDownList1.Items.Count == 0)
    {
        if (!Column.IsRequired) {
            DropDownList1.Items.Add(new ListItem("[Not Set]", ""));
        }

        PopulateListControl(DropDownList1);
        LinkButton1.OnClientClick = @"javascript:fk_dropdown_id = '{0}';window.open('{1}', '{2}', config='{3}');return false;".FormatWith(
            DropDownList1.ClientID,
            ForeignKeyColumn.ParentTable.GetPopupActionPath(PageAction.Insert),
            "fk_popup_" + ForeignKeyColumn.ParentTable.Name, "height=400,width=600,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no");
    }
    if (Request["__eventargument"] == "refresh")
    {
        DropDownList1.Items.Clear();
        if (!Column.IsRequired)
        {
            DropDownList1.Items.Add(new ListItem("[Not Set]", ""));
        }

        PopulateListControl(DropDownList1);
        DropDownList1.SelectedIndex = DropDownList1.Items.Count - 1;
    }
}

最后是我使用的两个扩展函数(放在你想放的地方):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Web.DynamicData;
using System.Web.UI;

public static class Utils
{
    [DebuggerStepThrough]
    public static string FormatWith(this string s, params object[] args)
    {
        return string.Format(s, args);
    }

    public static string GetPopupActionPath(this MetaTable mt, string action)
    {
        return new Control().ResolveUrl("~/{0}/popup_{1}.aspx".FormatWith(mt.Name, action));
    }
}

在您的 global.asax 中,通过更改该行来注册新路由:

Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert|popup_Insert" }),

好吧,我希望我没有忘记任何东西......它当然可以改进,但它确实有效。 好的,我希望有些人会觉得这很有用,它使 ASP.NET 动态数据变得更好;)。我现在要看看多对多关系。

【讨论】:

    【解决方案2】:

    收件人:VB.net 用户

    如果您像我一样对动态数据的复杂性和混乱程度感到愤怒,那么这是给您的!我花了 100 多个小时才弄明白 DD 的基础知识(尽管我非常精通其他数据库编程技术)。

    对于我们来说,Guillaume 的解决方案比 Naughton 的解决方案要容易得多。在尝试翻译 Naughton 的 15 多个小时后,我尝试翻译 Guillaume 的代码,我只花了 2 个小时就开始工作。这里的顺序是一样的。 (注:cs 扩展当然翻译成 vb 扩展)

    1. 忽略 admin.master.cs 指示。

    2. 执行 admin_popup.master 代码。如果您仍在使用 VS 2008 或更早版本,您将在内联块引用上收到 CSS 错误。忽略错误。

    3. 主文件 OnInit 子:

      Protected Overrides Sub OnInit(ByVal e As EventArgs)
      MyBase.OnInit(e)
      System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType, "refresh_fks", "     var fk_dropdown_id;     function refresh() {         __doPostBack(fk_dropdown_id,'refresh');     };", True)
      System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType, "resize_window", "function resizeWindow() {         window.resizeTo(document.body.clientWidth + 120, document.body.clientHeight + 120);         window.innerHeight = document.body.clientHeight + 5;         window.innerWidth = document.body.clientWidth;     }", True)
      System.Web.UI.ScriptManager.RegisterClientScriptBlock(Page, Page.GetType, "update_parent", "function updateParent() {        window.opener.location.reload(true);     }", True)
      

      结束子

    4. 将自定义页面下 (popup_Insert.aspx.vb) 中的事件替换为:

      Protected Sub DetailsView1_ItemCommand(ByVal sender As Object, ByVal e As DetailsViewCommandEventArgs)
      If e.CommandName = DataControlCommands.CancelCommandName Then
          System.Web.UI.ScriptManager.RegisterClientScriptBlock(Me, Me.GetType, "Close_Window", "self.close();", True)
      End If
      

      结束子 Protected Sub DetailsView1_ItemInserted(ByVal sender As Object, ByVal e As DetailsViewInsertedEventArgs) If e.Exception is Nothing OrElse e.ExceptionHandled Then System.Web.UI.ScriptManager.RegisterClientScriptBlock(Me, Me.GetType, "Close_Window", "window.opener.location.reload(true); self.close();", True) 万一 结束子

    5. 从 ForeignKey_Edit 创建一个自定义 FieldTemplate 并将其命名为 ForeignLinkKey_Edit.ascx。在 dropdownlist1 控件之后,添加两个空格 (),然后按照他的说明创建 asp:LinkBut​​ton。输入诸如“添加__”之类的文本或类似的内容。将页面加载功能替换为:

      Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      If DropDownList1.Items.Count = 0 Then
          If Not Column.IsRequired Then
              DropDownList1.Items.Add(New ListItem("[Not Set]", ""))
          End If
          PopulateListControl(DropDownList1)
      
          LinkButton1.OnClientClick = "javascript:fk_dropdown_id = '" & DropDownList1.ClientID & _
      

      "';window.open('" & ForeignKeyColumn.ParentTable.GetActionPath("Insert").Replace("Insert.aspx", "popup_Insert.aspx") & _ "', '" & "fk_popup_" & ForeignKeyColumn.ParentTable.Name & "', config='" & _ "height=400,width=400,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no" & "');return false;" 万一 If Request("__eventargument") = "refresh" Then DropDownList1.Items.Clear() If Not Column.IsRequired Then DropDownList1.Items.Add(New ListItem("[Not Set]", "")) 万一 PopulateListControl(DropDownList1) DropDownList1.SelectedIndex = DropDownList1.Items.Count - 1 万一 结束子

    6. 忽略扩展功能。

    7. 执行建议的更新路由。注意:如果您使用自定义路由,则必须对其进行修改,直到路由正确为止。

    【讨论】:

      【解决方案3】:

      或者我刚刚在这里创建了两个服务器控件和一篇博文: A Popup Insert control for Dynamic Data 的作用几乎相同,但将弹出功能封装在服务器控件中,将值 bak 从弹出窗口传递到主窗口和弹出按钮。

      【讨论】:

        【解决方案4】:

        VS2010 RC 的动态数据有什么新功能吗?在这个 RC 下,我们是否仍需要借助诸如此类的 hack 来获取动态数据中的简单 Master-Details?

        期待VS2010 RC下DD的一些博文……

        【讨论】:

        • 这周我会试着拿出一些。
        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 2017-02-22
        • 2016-09-13
        • 2011-11-16
        • 1970-01-01
        • 2018-10-15
        • 1970-01-01
        相关资源
        最近更新 更多