题
在 ASP.NET 动态数据的脚手架页面中,如果实体具有外键字段,并且您查找的值不在主键表中,即不在下拉列表中,您必须放弃对该实体的编辑,将查找的外键值添加到其表中,然后返回到原始实体。
我如何才能向外键字段模板添加“新建”链接/按钮,这将打开一个新窗口(使面板可见),您可以在其中添加所需的值,然后刷新下拉列表?
解决方案
你的意思是像在 django admin ui 中一样;)。我目前正在尝试实现该功能,如果我能正常工作,我将在此处发布代码。
编辑:
好的,我成功了,完整的 django 风格......解释起来有点长,但实际上很简单。
要创建的文件:
admin_popup.master 有一个漂亮的弹出页面(复制不带标题的 admin.master)。
一个 popup_Insert.aspx,其中 admin_popup.master 作为主服务器。(复制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中,添加一个LinkButton (ID=LinkButton1),并在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 动态数据变得更好;)。我现在要看看多对多关系。
其他提示
收件人:VB.net 用户
如果您像我一样对动态数据的复杂性和混乱程度感到愤怒,那么这就是为您准备的!我花了 100 多个小时才弄清楚 DD 的基础知识(尽管我非常精通其他数据库编程技术)。
对于我们来说,纪尧姆的解决方案比诺顿的解决方案容易得多。经过 15 个多小时的尝试翻译 Naughton 的代码后,我尝试翻译 Guillaume 的代码,只花了 2 个小时就开始工作。这里也是按照同样的顺序。(笔记:cs 扩展当然会转换为 vb 扩展)
忽略 admin.master.cs 指示。
执行 admin_popup.master 代码。如果您仍在使用 VS 2008 或更早版本,您会在内联块引用上收到 CSS 错误。忽略该错误。
主文件 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)
结束子
将自定义页面下的 (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
如果e.exception是e. eSecception,则end sub受保护的子详细信息view1_iteminserted(byval sender作为对象,byval e作为对象,byviewinsertedeventargs),而没有任何内容。 opener.location.reload(true);self.close();“,true)结束如果结束
根据ForeignKey_Edit 创建自定义FieldTemplate 并将其命名为ForeignLinkKey_Edit.ascx。在 dropdownlist1 控件后面添加两个空格 ( ),然后按照他的说明创建 asp:LinkButton。输入“Add __”之类的文字。将页面加载函数替换为:
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('”&foreferkeycolumn.parenttable.getActionPath(“ insert”)。替换(“ insert.aspx”,“ popup_insert.aspx”)&_''','','&fk_popup_&forefernkeycolumm.parenttable.parrenttable.parenttable.parenttable.parenttable.parenttable 。 “');返回false;''如果请求(“ __ __ eventargument”)=“ refresh”,然后dropdownlist1.items.clear()如果不是列。 (dropdownlist1)dropdownlist1.selectedIndex = dropdownlist1.items.count -1结束如果结束sub
忽略扩展功能。
执行建议的更新路由。笔记:如果您使用自定义路由,则必须对其进行修改,直到路由正确为止。
或者我刚刚在这里创建了两个服务器控件和一篇博文: 动态数据的弹出插入控件它几乎完全相同,但封装了服务器控件中的弹出功能,将值bak从弹出窗口传递到主窗口和弹出按钮。
VS2010 RC中动态数据的任何新功能?在这个RC下,我们是否仍然需要使用这些黑客来获取动态数据中的简单主数据?
期待在VS2010 RC下的一些关于DD的博客文章......