Jas*_*ban 6 c# asp.net ibindabletemplate 2-way-object-databinding
这个问题最初是关于双向绑定工作,但由于缺乏具体的答案和其他方面的进展,我一直在更新它 - 你可以检查编辑历史,但我认为这是更好的明晰.
下面的代码列表允许单个对象与模板化控件进行双向数据绑定.我想以最简单的方式扩展此示例,以允许为最根对象的复杂类型属性嵌套类似的双向数据绑定启用的模板化控件.例如,SampleFormData有一个属性List<string> Items.我希望能够在最根本模板(从此代码清单)中绑定到此列表,并在可编辑的文本框列表中显示字符串数据,可能还有插入,删除,重新绑定输入的命令-changes(返回绑定对象的List属性).此外,如果这是一个复杂类型的列表(SampleFormChildData而不是字符串),则SampleSpecificEntryForm可以在列表中使用新的嵌入式,绑定到每个列表的项目,如转发器.如果作者如此选择,那么直到叶子简单的属性.ui-fields不需要自动生成,只能用于绑定.
注意:这种情况List<string>很特殊,因为即使内置绑定也不能直接处理字符串作为DataItem - 直接绑定到字符串作为列表中的项目不是必需的,但肯定是有价值的.
这与a不同,FormView因为它不是为了期望绑定到项目列表中的一个,而是仅绑定到在viewstate中持久存在的单个项目.与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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用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>
Run Code Online (Sandbox Code Playgroud)
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我也实现了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>
Run Code Online (Sandbox Code Playgroud)
关于如何以级联方式进行此工作的任何想法都很棒(例如,在Items列表属性上).这里的挑战之一是Bind()不能引用数据绑定对象本身(在这种情况下是一个字符串)但是在该项的属性上 - 使得对列表的绑定变得笨拙.
谢谢你的帮助!
实现了IDataItemContainer.我非常希望能解决这个问题,但不会.没有明显的变化. 糟糕,在错误的类上实现它.现在它是Binding,但是值不会在回发时反弹到绑定对象.嗯...
正如本文所述,Page.GetDataItem()是异常的来源.如果页面的_dataBindingContext为null或为空,则抛出此异常.本文确实解释了这一点,但没有说明如何确保填充Page的_dataBindingContext.我会继续寻找.
正如MSDN文档所述,DataBoundControl应该实现PerformDataBinding而不是覆盖DataBind().我已经这样做了并且做了双向绑定工作.这段代码是必要的还是我应该使用内置的东西?
您是否尝试过Databinder.Eval(Container.DataItem,...)语法?
另请参阅有关Bind()的这篇文章。
附言。除非您使用 Viewstate 来保留值,否则您需要在每次回发时进行数据绑定。
| 归档时间: |
|
| 查看次数: |
3945 次 |
| 最近记录: |