两个向数据绑定的一个定义模板asp.net 控制
-
27-09-2019 - |
题
这个问题最初获得两种方式结合在所有的工作,但由于缺乏具体的答案,否则进展,我一直在更新它-你可以检查编辑的历史,但是我想这是最好的清晰度。
代码下面列出允许一个单一的对象是两个向数据绑定一个模板的控制。我想延长这个实例中最简单的方法可能允许筑巢的同样两个方数据绑定启用模板的控制复杂类型的属性的根大多数对象。例如, SampleFormData
有一个酒店 List<string> Items
.我想要能够结合该名单内根大多数的模板(从这个代码清单),并显示的串的数据可编辑列表的文本框,也许,命令插入、删除、重新绑定输入的变化(回到约束的对象的名单财产)。此外,如果这是一个列表中的一个复杂的类型(SampleFormChildData
, 而不是string),一个新的嵌入式 SampleSpecificEntryForm
可能是内使用的列表,约束每个列表中的项目,如中继器。等下来的树叶的简单性质,如果提交人所选择。Ui-领域需要的不是自动产生,就可结合。
注:情况下 List<string>
是特殊的,因为甚至是内在的绑定不能处理串的数据项直接结合到串直接作为项目在我们的名单不是一个要求,但肯定有价值的。
这是不同的 FormView
因为它不是建造期望结合到一个列表中的项目,只有一个项目因持续存在视图状态中或在那里过。不像FormView,这只有一个默认的模板类似于FormView的EditTemplate.同样,结合收集样性也只有一个图编辑。没有选择行,然后编辑。一切都是可编辑所有的时间。目的是使两种方式结的形式更易于建造。
在我看来,应该有两种结合。 SingleEntityBinding
和 CollectionBinding
. SingleEntityBinding
需要一个单一的物体实例作为一个数据源(作为原型的 SampleSpecificEntryForm
)的同时 CollectionBinding
可以开它的父母 SingleEntityBinding
有属性的 DataSourceID="EntryForm1" DataMember="Items"
如在码的例子 DataList1
如下。筑巢的任何类型应当支持在任何类型。名单的操纵,例如插入、更改和删除的类型操作对后备对象的数据的责任形式作作者;然而,这种机制将是实施起来相对简单。
这里的一些代码,希望它能帮助别人。200点都有更好的建议朝着这个规定出目标...
using System.ComponentModel;
using System.Collections.Specialized;
using System.Collections.Generic;
namespace System.Web.UI.WebControls.Special
{
[Serializable]
public class SampleFormData
{
public string SampleString { get; set; }
public int SampleInt { get; set; }
public List<string> Items { get; set; }
public SampleFormData()
{
SampleString = "Sample String Data";
SampleInt = 5;
Items = new List<string>();
}
}
[ToolboxItem(false)]
public class SampleSpecificFormDataContainer : WebControl, INamingContainer, IDataItemContainer
{
SampleSpecificEntryForm entryForm;
internal SampleSpecificEntryForm EntryForm
{
get { return entryForm; }
}
[Bindable(true), Category("Data")]
public string SampleString
{
get { return entryForm.FormData.SampleString; }
set { entryForm.FormData.SampleString = value; }
}
[Bindable(true), Category("Data")]
public int SampleInt
{
get { return entryForm.FormData.SampleInt; }
set { entryForm.FormData.SampleInt = value; }
}
[Bindable(true), Category("Data")]
public List<string> Items
{
get { return entryForm.FormData.Items; }
set { entryForm.FormData.Items = value; }
}
internal SampleSpecificFormDataContainer(SampleSpecificEntryForm entryForm)
{
this.entryForm = entryForm;
}
#region IDataItemContainer Members
public object DataItem { get { return entryForm.FormData; } }
public int DataItemIndex { get { return 0; } }
public int DisplayIndex { get { return 0; } }
#endregion
}
public class SampleSpecificEntryForm : DataBoundControl, INamingContainer, IDataSource
{
#region Template
private IBindableTemplate formTemplate = null;
[Browsable(false), DefaultValue(null),
TemplateContainer(typeof(SampleSpecificFormDataContainer), ComponentModel.BindingDirection.TwoWay),
PersistenceMode(PersistenceMode.InnerProperty)]
public virtual IBindableTemplate FormTemplate
{
get { return formTemplate; }
set { formTemplate = value; }
}
#endregion
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return base.Controls;
}
}
private SampleSpecificFormDataContainer formDataContainer = null;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SampleSpecificFormDataContainer FormDataContainer
{
get
{
EnsureChildControls();
return formDataContainer;
}
}
[Bindable(true), Browsable(false)]
public SampleFormData FormData
{
get
{
SampleFormData data = ViewState["FormData"] as SampleFormData;
if (data == null)
{
data = new SampleFormData();
ViewState["FormData"] = data;
}
return data;
}
}
protected override void CreateChildControls()
{
if (!this.ChildControlsCreated)
{
this.ChildControlsCreated = true;
Controls.Clear();
formDataContainer = new SampleSpecificFormDataContainer(this);
Controls.Add(formDataContainer);
FormTemplate.InstantiateIn(formDataContainer);
}
}
protected override void PerformDataBinding(Collections.IEnumerable ignore)
{
CreateChildControls();
if (Page.IsPostBack)
{
//OrderedDictionary fields = new OrderedDictionary();
//ExtractValuesFromBindableControls(fields, formDataContainer); // Don't know what this would be for
foreach (System.Collections.DictionaryEntry entry in formTemplate.ExtractValues(formDataContainer))
{
if (((string)entry.Key).Equals("SampleString", StringComparison.Ordinal))
{
FormData.SampleString = (string)entry.Value;
}
if (((string)entry.Key).Equals("SampleInt", StringComparison.Ordinal))
{
int i;
if (int.TryParse((string)entry.Value, out i))
{
FormData.SampleInt = i;
}
}
}
}
formDataContainer.DataBind();
}
public SampleSpecificEntryForm()
{
this.PreRender += new EventHandler(SampleSpecificEntryForm_PreRender);
}
void SampleSpecificEntryForm_PreRender(object sender, EventArgs e)
{
SaveViewState();
}
#region IDataSource Members
public event EventHandler DataSourceChanged;
public DataSourceView GetView(string viewName)
{
return new PropertyView(this, viewName);
}
public Collections.ICollection GetViewNames()
{
return new List<string>() { "SampleString", "SampleInt", "Items" };
}
#endregion
}
// Not yet used ...
public class PropertyView : DataSourceView
{
SampleSpecificEntryForm owner;
string viewName;
protected override Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
{
if (viewName.Equals("SampleString", StringComparison.Ordinal))
{
return new object[] { owner.FormData.SampleString };
}
if (viewName.Equals("SampleInt", StringComparison.Ordinal))
{
return new object[] { owner.FormData.SampleInt };
}
if (viewName.Equals("Items", StringComparison.Ordinal))
{
return new object[] { owner.FormData.Items };
}
throw new InvalidOperationException();
}
public PropertyView(SampleSpecificEntryForm owner, string viewName)
: base(owner, viewName)
{
this.owner = owner;
this.viewName = viewName;
}
}
}
有一个ASP.NET 页面下:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default2.aspx.cs" Inherits="EntryFormTest._Default2" EnableEventValidation="false" %>
<%@ Register Assembly="EntryForm" Namespace="System.Web.UI.WebControls.Special" TagPrefix="cc1" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<cc1:SampleSpecificEntryForm ID="EntryForm1" runat="server">
<FormTemplate>
<asp:TextBox ID="txtSampleString" runat="server" Text='<%# Bind("SampleString") %>'></asp:TextBox><br />
<asp:TextBox ID="txtSampleInt" runat="server" Text='<%# Bind("SampleInt") %>'></asp:TextBox><br />
<h3>
(<%# Container.SampleString %>, <%# Container.SampleInt %>) - aka -
(<%# DataBinder.Eval(Container, "SampleString")%>, <%# DataBinder.Eval(Container, "SampleInt")%>)</h3>
<br />
<asp:Button ID="btnUpdate" runat="server" Text="Update" /><br />
<br />
</FormTemplate>
</cc1:SampleSpecificEntryForm>
</asp:Content>
Default2.aspx。cs:
using System;
namespace EntryFormTest
{
public partial class _Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
EntryForm1.DataBind();
}
}
}
我已经实现IDataSource以及,以试图能够窝的一个列表中的成分一样(内部):
<asp:DataList ID="DataList1" runat="server" DataSourceID="EntryForm1" DataMember="Items">
<EditItemTemplate>
<asp:TextBox ID="TextBox3" runat="server" Text="<%# Bind(".") %>"></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:Button ID="Button2" runat="server" Text="Add" CommandName="Add" />
</FooterTemplate>
</asp:DataList>
任何想法上如何使这项工作在级联的方式将是巨大的(在项目列出的财产,例如)。面临的挑战之一是,Bind()可以不参考数据绑定的对象本身(a string在这种情况下),但在一个酒店的这一项目的制定结合到一个列表中的尴尬。
感谢任何的帮助!
发现的沿途
实现IDataItemContainer.我非常希望,这将解决这个问题,但没有。没有显着变化。 哎呀,实现它在错误的一类。现在它是有约束力,但数值不被反弹的约束对象在回发。嗯...
作为 这篇文章 所建议的,页。GetDataItem()是例外。这个异常,如果网页的_dataBindingContext是空或空。该条并解释这一点,但它没有说明如何确保该网页的_dataBindingContext是填充。我会继续寻找。
作为MSDN文件说。应当实施PerformDataBinding而不是重写据绑定().我已经这样做了,并由两种方式结合的工作。这是码必要的或者我应该使用什么建?
解决方案