有没有ASP ?. NET databinable控件(如Repeater),它只需要一个项目
本文关键字:项目 一个 控件 databinable NET ASP 有没有 Repeater | 更新日期: 2023-09-27 18:11:23
我正在尝试在Web表单上显示来自业务对象的许多属性。当然,我可以创建大量的标签,并在代码隐藏中分配所有的值,但我觉得必须有一种不那么冗长的方法。
我想要的是类似于asp:Panel的东西,但是你可以指定一个数据源。面板似乎不支持任何类型的数据绑定。
我想要的是这样的东西
// C#
panel.DataSource = theCompany;
panel.DataBind();
:
// ASPX
<asp:Panel runat="server">
Name: <%# Eval("Name") %>
Phone: <%# Eval("Phone") %>
...
</asp:Panel>
. .但是我找不到可以让我这样工作的工作。
我想我可能能够使用asp:FormView,但这只是给出了错误"数据源是无效类型。它必须是IListSource、IEnumerable或IDataSource。"
一个警告是,我不想要调用一个全局的DataBind()(这在过去给我们带来了没完没了的问题)-我希望将数据绑定限制在页面的特定部分。
似乎你可以使用面板来做到这一点,但是你必须首先将你的业务对象分配给页面属性,因为没有办法将业务对象设置为面板的"数据源"(就像你对Repeater控件一样,例如)。
一旦对象被指定为页面属性,您就可以在.aspx中使用以下语法来访问该对象的属性,而无需在后面的代码中手动为每个项分配控制值:
<%# Company.Name %>
您不需要进行数据绑定(尽管您可以)。您需要的是一个简单的表达式求值器。在后面的代码中添加如下属性
public string Test { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
Test = "<script>alert('test');</script>";
}
然后使用它将代码直接呈现到页面,如下所示
The value: <%: Test %>
注意<%:语法转义输入。如果希望不转义输入,则可以使用<%=语法。注意,你不需要有一个字符串对象,你可以访问任何你喜欢的属性,例如
The value lenght: <%: Test.Length %>
使用如下:
<asp:DetailsView runat="server">
Name: <%# Eval("Name") %>
Phone: <%# Eval("Phone") %>
</asp:DetailsView>
使用DetailsView
。您可以从工具箱中添加它。它用于单行数据表示。
<asp:DetailsView runat="server">
Name: <%# Eval("Name") %>
Phone: <%# Eval("Phone") %>
</asp:DetailsView>
为什么不使用DetailsView ?这正是你想要的。仅显示单行数据,并且也是两列形式
我建议使用标准的Repeater
,与包含单个项目的数组绑定。
Repeater.DataSource = new [] { theCompany };
Repeater.DataBind();
优于绑定到Panel
的优势:您仍然可以使用ItemType
属性,并且可以访问不错的强类型Item
对象,而不必使用Eval
,即:
<asp:Repeater runat="server" Id="Repeater" ItemType="CompanyViewModel">
<ItemTemplate>
Name: <%# Item.Name %>
Phone: <%# Item.Phone %>
</ItemTemplate>
</asp:Repeater>
(将"CompanyViewModel"替换为"the company "的类型)
您也可以尝试使用DetailsView
,但它不像Repeater那样具有可塑性。
创建显示对象属性的用户控件。您可以使用反射读取属性名称和值并在控件中显示。
在用户控件中为对象创建属性。在用户控制代码后面写函数Show()和下面的代码。
//Build html strin from all propeties
PropertyInfo[] properties = yourObject.GetType().GetProperties();
string lbl = "<label>{0}</label>";
string value= "<span>{0}</span>";
string tab ="'t";
StringBuilder sb = new StringBuilder();
foreach (PropertyInfo pi in properties)
{
var label = string.Format(lbl,pi.Name);
var val = string.Format(value, pi.GetValue(yourObject, null))
sb.Append(label+tab+val);
sb.Append("<br/>")
}
Response.Write(sb.ToString());
现在在页面中添加该控件并在后面的代码中设置其对象属性,如
myControl.MyObject = yourObject;
myControl.Show();
NickG的回答会起作用…但是考虑两种情况。
-
如果您的业务对象为null,则页面将崩溃并出现"对象引用"错误。这可以通过繁琐的外观来避免% if(MyObject != null) {%><%= MyObject。Prop %><%} %>…但是每次这样做都会导致代码混乱。
-
如果你的页面通过UpdatePanel使用PostBack处理,业务对象将不得不在每次页面生命周期运行时重新加载到属性…,即使页面的那一部分没有被重绘。这是因为IIS将解析所有的<%= MyObject。如果您的对象来自数据库,则会导致浪费CPU周期和可能浪费的数据库调用。
<asp:Repeater ID="rptTest" runat="server">
<ItemTemplate>
Request.URL = <%# Eval("Url") %>
</ItemTemplate>
</asp:Repeater>
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var objTest = Request; //Using the Request object as a test business object
rptTest.DataSource = new List<System.Web.HttpRequest>() { objTest };
rptTest.DataBind();
}
}
要做到这一点,我们可以自定义ASP。. NET面板,通过继承它并使用自定义服务器控件。净
使用下面的代码修改ASP。. NET面板。. NET自定义服务器控件项目:
[DefaultProperty("Text")]
[ToolboxData("<{0}:CustomPanel runat=server></{0}:CustomPanel>")]
public class CustomPanel : Panel
{
[Bindable(true)]
public object MyDataSource
{
get;
set;
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public StringBuilder Text
{
get;
set;
}
public void MyDataBind()
{
Text = new StringBuilder();
foreach (PropertyInfo p in MyDataSource.GetType().GetProperties())
{
Text.Append(string.Format("<b>{0}</b>", p.Name));
Text.Append(":");
if (p.GetIndexParameters() == null || p.GetIndexParameters().Length == 0)
Text.Append(p.GetValue(MyDataSource, null));
Text.Append("<br />");
}
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write(Text);
}
}
然后将此控件的引用和工具箱项添加到您的ASP。NET页面:
<cc2:CustomPanel ID="MyCustomPanel" runat="server">
</cc2:CustomPanel>
使用如下所示的控件:
MyCustomPanel.MyDataSource = theCompany;
MyCustomPanel.MyDataBind();