问题
I have a listview that displays a list of textboxes that get created on a button click. I would also like a label to be created next to each txtbox that would increment what is says from step x: to step x+1:
Do I need to create another listview control for this, or is there a much easier way (which I hope)?
Here is the current web code for my listview:
<tr align="center" valign="middle">
<td>
<asp:ListView ID="lvDynamicTextboxes" runat="server" ItemPlaceholderID="itemPlaceholder" onitemdatabound="lvDynamicTextboxes_ItemDataBound">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<asp:Label ID="lblStep" runat="server" Text="Step 1:" />
<asp:TextBox ID="txtStep" runat="server" TextMode="MultiLine" Rows="3" Width="300" style="margin-top:10px;" />
</ItemTemplate>
</asp:ListView>
<br /><asp:Button ID="btnAddNewStep" runat="server" Text="Add another step" onclick="btnAddNewStep_Click" style="margin-top:5px;" />
</td>
</tr>
And here is the code-behind
protected void btnAddNewStep_Click( object sender, EventArgs e )
{
this.UpdateDataSource();
this.IncrementTextboxCount();
this.BindListView();
}
private void BindListView()
{
//create an enumerable range based on the current count
List< string > dataSource = this.GetDataSource();
//bind the listview
this.lvDynamicTextboxes.DataSource = dataSource;
this.lvDynamicTextboxes.DataBind();
}
private void IncrementTextboxCount()
{
List< string > dataSource = this.GetDataSource();
dataSource.Add( string.Empty );
this.SetDataSource( dataSource );
}
private List< string > GetDataSource()
{
List< string > dataSource = null;
if ( ViewState[ "DataSource" ] != null )
dataSource = ( List< string > )ViewState[ "DataSource" ];
else
{
dataSource = new List< string >();
dataSource.Add( string.Empty );
ViewState[ "DataSource" ] = dataSource;
}
return dataSource;
}
private void UpdateDataSource()
{
List< string > dataSource = new List< string >();
foreach ( ListViewItem item in this.lvDynamicTextboxes.Items )
if ( item is ListViewDataItem )
{
TextBox txt = (TextBox)item.FindControl( "txtStep" );
dataSource.Add( txt.Text );
}
this.SetDataSource( dataSource );
}
protected void lvDynamicTextboxes_ItemDataBound( object sender, ListViewItemEventArgs e )
{
if ( e.Item is ListViewDataItem )
{
TextBox txt = (TextBox)e.Item.FindControl( "txtStep" );
txt.Text = ( (ListViewDataItem)e.Item ).DataItem.ToString();
}
}
private void SetDataSource( List< string > dataSource )
{
ViewState[ "DataSource" ] = dataSource;
}
EDIT::
Since there seems to be a bit of confusion, I'll try to clarify:
As of now, I have a textbox in a listview with a button underneath.
________
| txtbox |
|________|
_____
|_btn_|
When you click a button, it generates another text box, so clicking it twice results in this:
________
| txtbox |
|________|
________
| txtbox |
|________|
________
| txtbox |
|________|
_____
|_btn_|
These textboxes are to create steps in a process, so all I would like to do is add a generated label next to each generated textbox to say which step it is. So I want it to look like this:
________
["Step 1"] | txtbox |
|________|
________
["Step 2"] | txtbox |
|________|
________
["Step 3"] | txtbox |
|________|
_____
|_btn_|
And if they click the button again, then another label is generated with the text "Step 4"
回答1:
Looks like you've got all the code you need... just missing one thing... add a private class variable that gets set to 0 on Page_Load. Then increment it in your ItemDataBound to get the current step number. Then call FindControl for your label, just like for the text box... and change lblStep.Text to "Step X". Nothin' to it.
回答2:
I would suggest for future reference in BindListView() before binding a DataSource to ListView, create yourself a new list of objects, which then you can easily bind, like this:
this.lvDynamicLabels.DataSource =
from items in lblDataSource
select new
{
Value = items,
Index = strings.IndexOf(items) + 1
};
and simply bind data in Listview:
<asp:Label ... Text='<%# Bind(Index) %>' />
<asp:Button ... Text='<%# Bind("Value")%>' />
, plus you can dismiss method IncrementTextboxCount now, and also customize Index value ( make into "Step1", now its "1")
回答3:
I ended up making duplicate functions for another listview that contained the labels and then putting them in a table. It's not pretty, but it works. I've also added a remove link next the newest textbox. Just a heads up for anyone looking through the code.
<table>
<tr>
<td valign="top">
<asp:ListView ID="lvDynamicLabels" runat="server" ItemPlaceholderID="itemPlaceholder2" onitemdatabound="lvDynamicLabels_ItemDataBound">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder2" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<asp:Label ID="lblStep" runat="server" Width="100px" style="margin-top:30px; margin-bottom:16px;" />
</ItemTemplate>
</asp:ListView>
</td>
<td>
<asp:ListView ID="lvDynamicTextboxes" runat="server" ItemPlaceholderID="itemPlaceholder" onitemdatabound="lvDynamicTextboxes_ItemDataBound">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<asp:TextBox ID="txtStep" runat="server" TextMode="MultiLine" Rows="3" Width="275px" style="margin-top:10px;" />
</ItemTemplate>
</asp:ListView>
<asp:LinkButton ID="lnkRemove" runat="server" Text="Remove" Visible="false" OnClick="lnkRemove_Click" style="font-size:small; position:absolute; margin-top:30px;" />
<br /><asp:Button ID="btnAddNewStep" runat="server" Text="Add another step" onclick="btnAddNewStep_Click" style="margin-top:5px;" />
</td>
</tr>
</table>
And the code behind:
protected void lnkRemove_Click( object sender, EventArgs e )
{
UpdateDataSource( true );
UpdateLabelDataSource( true );
BindListView();
BindLabelListView();
if ( lvDynamicTextboxes.Items.Count == 1 )
lnkRemove.Visible = false;
}
private void BindListView()
{
List< string > dataSource = this.GetDataSource();
this.lvDynamicTextboxes.DataSource = dataSource;
this.lvDynamicTextboxes.DataBind();
}
private void IncrementTextboxCount()
{
List< string > dataSource = this.GetDataSource();
dataSource.Add( string.Empty );
this.SetDataSource( dataSource );
}
private List< string > GetDataSource()
{
List< string > dataSource = null;
if ( ViewState[ "DataSource" ] != null )
dataSource = ( List< string > )ViewState[ "DataSource" ];
else
{
dataSource = new List< string >();
dataSource.Add( string.Empty );
ViewState[ "DataSource" ] = dataSource;
}
return dataSource;
}
private void UpdateDataSource( bool delete )
{
List< string > dataSource = new List< string >();
foreach ( ListViewItem item in this.lvDynamicTextboxes.Items )
if ( item is ListViewDataItem )
{
TextBox txt = (TextBox)item.FindControl( "txtStep" );
dataSource.Add( txt.Text );
}
if ( delete )
dataSource.RemoveRange( dataSource.Count-1, 1 );
this.SetDataSource( dataSource );
}
protected void lvDynamicTextboxes_ItemDataBound( object sender, ListViewItemEventArgs e )
{
if ( e.Item is ListViewDataItem )
{
TextBox txt = (TextBox)e.Item.FindControl( "txtStep" );
txt.Text = ( (ListViewDataItem)e.Item ).DataItem.ToString();
}
}
private void SetDataSource( List< string > dataSource )
{
ViewState[ "DataSource" ] = dataSource;
}
private void BindLabelListView()
{
List< string > lblDataSource = this.GetLabelDataSource();
//bind the listview
this.lvDynamicLabels.DataSource = lblDataSource;
this.lvDynamicLabels.DataBind();
}
private void IncrementLabelCount()
{
List< string > lblDataSource = this.GetLabelDataSource();
lblDataSource.Add( "Step " + ( lblDataSource.Count + 1 ) );
this.SetLabelDataSource( lblDataSource );
}
private List< string > GetLabelDataSource()
{
List< string > lblDataSource = null;
if ( ViewState[ "lblDataSource" ] != null )
lblDataSource = ( List< string > )ViewState[ "lblDataSource" ];
else
{
lblDataSource = new List< string >();
lblDataSource.Add( "Step 1" );
ViewState[ "lblDataSource" ] = lblDataSource;
}
return lblDataSource;
}
private void UpdateLabelDataSource( bool delete )
{
List< string > lblDataSource = new List< string >();
int count = 1;
foreach ( ListViewItem item in this.lvDynamicLabels.Items )
if ( item is ListViewDataItem )
{
Label lbl = (Label)item.FindControl( "lblStep" );
lbl.Text = "Step " + count;
lblDataSource.Add( lbl.Text );
count++;
}
if ( delete )
lblDataSource.RemoveRange( lblDataSource.Count-1, 1 );
this.SetLabelDataSource( lblDataSource );
}
protected void lvDynamicLabels_ItemDataBound( object sender, ListViewItemEventArgs e )
{
if ( e.Item is ListViewDataItem )
{
Label lbl = (Label)e.Item.FindControl( "lblStep" );
lbl.Text = ( (ListViewDataItem)e.Item ).DataItem.ToString();
}
}
private void SetLabelDataSource( List< string > lblDataSource )
{
ViewState[ "lblDataSource" ] = lblDataSource;
}
回答4:
I don't understand why you ended up seperating the label from the textbox. Why not leave the template as you had it originally, and have this method in your code behind:
protected void lvDynamicLabels_ItemDataBound( object sender, ListViewItemEventArgs e )
{
if ( e.Item is ListViewDataItem )
{
Label lbl = (Label)e.Item.FindControl( "lblStep" );
lbl.Text = "Step " + (datasource.Count + 1).ToString();
TextBox txt = (TextBox)e.Item.FindControl( "txtStep" );
txt.Text = ( (ListViewDataItem)e.Item ).DataItem.ToString();
}
}
来源:https://stackoverflow.com/questions/2060835/question-concerning-asplistview-and-multiple-dynamically-created-controls