Editing in ListView without EditMode on - asp.net

I have a class
public class MyClass
{
public int id {get; set;}
public string name {get; set;}
}
I store objects of type MyClass in list:
List<MyClass> listOfObjects {get; set;}
I want user to edit data. To display data I am using ListView control - I am binding listOfObject list to ListView:
<asp:ListView runat="server" ID="ListView1">
<LayoutTemplate>
<table runat="server" id="table1" >
<tr runat="server" id="itemPlaceholder" >
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id="tr" runat="server">
<td id="td1" runat="server">
<asp:TextBox ID="tb1" runat="server" Text='<%#Eval("id") %>' />
</td>
<td id="td2" runat="server">
<asp:TextBox ID="tb2" runat="server" Text='<%#Eval("name")%>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
So far so good, and everything works fine. I see the data in ListView.
I do not know how I can edit data in ListView without entering EditMode - I do not have Edit button, I have only textboxes to enter new data.
All I want is to bind data edited in textboxes in the opposite direction - into listOfObject list. I have tried many solutions
and nothing was working correctly...
I thought that I can read data this way:
var listItems = ListView1.Items.Cast<ListViewDataItem>().Select(a => new MyClass
{
id = ((TextBox)a.FindControl("tb1")).Text,
name = ((TextBox)a.FindControl("tb2")).Text
}).ToList<>();
but with this I get data which were in textbox before editing...
Help me please, because I have no idea how to make it working
(maybe it would be better to use ObjectDataSource?)

Where do you call the last part of your code? I suppose you have a submit button, do you call that code in it's Click EventHandler?
You must be overwriting your data. If you DataBind in the Page's Load event make sure you only do that if the page is not posting back.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// databind
}
}

Related

DataValueField pass value to repeater?

So if the user selects a value from a dropDownList and clicks the button, the ID is passed to the code behind(which is where I want it)
E.g.
<asp:DropDownList ID="DropDownList" runat="server" AppendDataBoundItems="true" DataTextField="Company_Name" DataValueField="id">
<asp:ListItem Text="---Select---" Value="0" />
</asp:DropDownList>
So dataValueField will pass the 'id' of the selected record in the DD.
However On the same page I am using a repeater to display records that have been previously chosen from the drop down, Beside each record i have a 'Change Prices' button which I want to perform a task when clicked, all works fine however all I need is the same 'id'.
So is this done in a similar way? E.g
<asp:Repeater ID="repeaterShowName" runat="server">
<HeaderTemplate>
<tr>
<th>
<asp:Label ID="SubConName" Text="Current SubContractors" runat="server"></asp:Label>
</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="SubCon" Text='<%# Bind ("Company_Name") %>' runat="server"></asp:Label>
</td>
<td>
<asp:LinkButton ID="AddNewBOQLink" runat="server" OnClick="EditPricesForSubContractor" CssClass="bottomhyperlink">Change Prices</asp:LinkButton>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
//So Do I add in DataValueField="id" inside the link button, so when the user selects the hyperlink beside the name, it will automatically have the 'id?
You should use the CommandArgument property of the LinkButton to pass the id to the method that handles the click.
So your LinkButton will now look like this:
<asp:LinkButton ID="AddNewBOQLink" runat="server" CommandArgument='<%# Bind("id")%>' CssClass="bottomhyperlink">Change Prices</asp:LinkButton>
And you want to add the following property to your Repeater:
<asp:Repeater .... OnItemCommand="repeater_Command" ...
The method that will handle the command event will look like this
void repeater_Command(Object Sender, RepeaterCommandEventArgs e) {
//retrieve the id like so
int id = (int)e.CommandArgument;
}
Also, note that I removed the OnClick property from the LinkButton. It is not needed as you are handling the click via the repeater's OnItemCommand method.
In addition, you may want to consider adding a CommandName propery to the LinkButton. This is used to identify which command you wish to execute. Currently, you only have a single command: Change Prices. But in the future you may want to add an additional button with a different command.
In order to do this, add the following property to the LinkButton:
<asp:LinkButton ... CommandName="ChangePrice" ...
And modify the repeater_Command method to handle the CommandName. Like so:
void repeater_Command(Object Sender, RepeaterCommandEventArgs e) {
switch(e.CommandName)
{
case "ChangePrice":
//retrieve the id like so
int id = (int)e.CommandArgument;
break;
}
}

How to get item click event in asp.net repeater control?

I am using a repeater control to show some data on my page.
The repeater item template has an image and a label field.
I want that when i click the image , I get an event containing the id field of my data item.
How can I achieve this ?
Actually when I click the image i want to go to another page and want to show detailed information of my data item, in repeater i m just showing short information.
My repeater looks like this:
<asp:Repeater ID="itemRepeater" runat="server" OnItemCreated="itemRepeater_ItemCreated" >
<ItemTemplate>
<tr>
<td colspan="2">
<asp:Image ID="phImage" runat="server" ImageUrl='<%#"~/ImageHandler.ashx?id=" + DataBinder.Eval(Container.DataItem, "PhotoID")%>' />
</td>
<td>
<asp:Label ID="lblImageName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
I want to get PhotoID in the event when i click the image.
My photo class looks like this:
public class PhotoDC
{
public byte[] ImagebyteArray { get; set; }
public string Name { get; set; }
public int PhotoID { get; set; }
}
I have been doing winform programming just started web, maybe it is easy but i m struggling to find a solution.
I somehow managed to show hand cursor when i hover the image though.
Try this:
<asp:Repeater ID="itemRepeater" runat="server" OnItemCreated="itemRepeater_ItemCreated" >
<ItemTemplate>
<tr>
<td colspan="2">
<asp:ImageButton ID="phImage" runat="server" ImageUrl='<%#"~/ImageHandler.ashx?id=" + DataBinder.Eval(Container.DataItem, "PhotoID")%>' OnCommand="Image_Click" CommandName="ImageClick" CommandArgument='<%# Eval("PhotoID") %>' />
</td>
<td>
<asp:Label ID="lblImageName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
protected void Image_Click(object sender, CommandEventArgs e)
{
if (e.CommandName == "ImageClick"){
//e.CommandArgument --> photoid value
//Do something
}
}
You can use ItemCommand of repeater control
like this -
protected void itemRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.CommandName == "img_Click") // check command is cmd_delete
{
// get you required value
int CustomerID = Convert.ToInt32(e.CommandArgument);
//Write some code for what you need
}
}
}
Personally I think the simplest way to handle something like this is to simply use the ItemTemplate to generate a regular html link, rather than do any thing in the code-behind. Something like this:
<asp:Repeater ID="itemRepeater" runat="server" OnItemCreated="itemRepeater_ItemCreated" >
<ItemTemplate>
<tr>
<td colspan="2">
<a href="/Details.aspx?id=<%=DataBinder.Eval(Container.DataItem, "PhotoID")%>">
<asp:Image ID="phImage" runat="server" ImageUrl='<%#"~/ImageHandler.ashx?id=" + DataBinder.Eval(Container.DataItem, "PhotoID")%>' />
</a>
</td>
<td>
<asp:Label ID="lblImageName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</td>
</tr>
</ItemTemplate>
I know this isn't strictly the question you asked, but IMHO it's the best approach to accomplish the task.

Passing parameter to user control inside repeater

I have a repeater that lists data including an ID that I pass to a user control that is not visible until I click a linkbutton. However, when I have clicked the linkbutton, the ID has been lost.
Anyone have any idea where I'm going wrong?
Here is the code for the repeater:
<asp:Repeater ID="uxPolicyList" runat="server" onitemdatabound="uxPolicyList_ItemDataBound">
<ItemTemplate>
<tr>
<td class="smaller-ctrl">
<img src="Assets/Images/home-icon.gif" alt="Home Insurance Policy" /><%#Eval("PolicyNumber")%>
</td>
<td>
<%#Eval("StartDate","{0:d}")%>
</td>
<td class="center-cell-ctrl">
<%#Eval("Renewal", "{0:d}")%>
</td>
<td class="center-cell-ctrl">
Postcode:<br />
<%#Eval("Postcode")%>
</td>
<td id='<%#Eval("PolicyNumber")%>' class="button-cell">
<asp:LinkButton ID="uxPolicySummaryButton" CssClass="policy-link-ctrl" CommandName="PolicyNumber" CommandArgument='<%#Eval("PolicyNumber")%>' OnCommand="uxPolicySummaryButton_Command" runat="server">Policy summary<br /></asp:LinkButton>
</td>
</tr>
<uc1:PolicySummary ID="uxPolicySummary" PolicyNumber='<%#Eval("PolicyNumber")%>' runat="server" Visible="false" />
</ItemTemplate>
I have these get/set accessors in the user control code-behind, but they're always blank:
public string _policyNumber = string.Empty;
public string PolicyNumber
{
get
{
return _policyNumber;
}
set
{
_policyNumber = value;
}
}
When testing, I hard coded a value in the user control. i.e.
<uc1:PolicySummary ID="uxPolicySummary" PolicyNumber="545545-5454-54545" runat="server" Visible="false" />
...and it worked fine. Any ideas appreciated
try to reassign value of PolicyNumber property inside OnCommand event with the value of CommandArgument
Edit
or save it into HiddenField inside your control
public string PolicyNumber
{
get
{
return MyHiddenField.Value;
}
set
{
MyHiddenField.Value = value;
}
}
I think you might be missing the ViewState backing store.
public string PolicyNumber
{
get { return ViewState["policyNumber"] as string; }
set { ViewState["policyNumber"] = value; }
}

How to read ListView data into generic List

I have a ListView which is filled by generic list of type MyClass. I can easily bind data from this list into ListView. But I have problems with reading data in opposite direction.
This is my class:
public class MyClass
{
public int id { get; set; }
public string name { get; set; }
}
I have also generic list of type MyClass:
List<MyTest> list = new List<MyTest>();
Finally I bind data to ListView this way:
ListView1.DataSource = list;
ListView1.DataBind();
My ListView template:
<asp:ListView runat="server" ID="ListView1">
<LayoutTemplate>
<table runat="server" id="table1" >
<tr runat="server" id="itemPlaceholder" ></tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id="tr" runat="server">
<td id="td1" runat="server">
<asp:TextBox ID="tb1" runat="server" Text='<%#Eval("id") %>' />
</td>
<td id="td2" runat="server">
<asp:TextBox ID="tb2" runat="server" Text='<%#Eval("name") %>' />
</td>
</tr>
</ItemTemplate>
How can I read data from ListView into my List list?
The operation of reading ListView data into List generic list should begin after clicking the button "GetData"
I can't test this, but I believe this will work:
using System.Linq;
List<MyClass> list = ListView1.DataSource.Cast<MyClass>().ToList();
UPDATE: As noted in the comments, that only works right after you set the DataSource. If you want to get the list on a post-back, try:
List<MyClass> list = ListView1.Items
.Select(lvi=>lvi.DataItem as MyClass)
.ToList();
You can get at the ListViewItem in an updating event like this:
<asp:ListView ID="ListView1" runat="server" OnItemUpdating="ListView1_ItemUpdating"></asp:ListView>
void ListView1_ItemUpdating(Object sender, ListViewUpdateEventArgs e)
{
ListViewItem item = ListView1.Items[e.ItemIndex];
// I think you should also be able to do if you are indeed binding with the type List<MyTest>
List<MyTest> item = (List<MyTest>)ListView1.Items[e.ItemIndex];
}
I can show you other ways if you describe more of what the scenario is that you need to get the data.

How to add a <td> tag to ListViewItem?

I want to implement an apperance as this article mentioned using nested ListView control. However, in my scenario, I cannot use EntityDataSource control so I bind data manually.
My table:
Categories
PK: UniqueId, Guid
Name, string
ParentId, Guid
<asp:ListView ID="CategoryList" runat="server"
onitemdatabound="CategoryList_ItemDataBound">
<LayoutTemplate>
<table>
<asp:PlaceHolder ID="itemPlaceHolder" runat="server"></asp:PlaceHolder>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td colspan="2"><%# Eval("Name") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
protected void Page_Load(object sender, EventArgs e)
{
using (PractiseEntities context = new PractiseEntities()) {
var result = from categories in context.Categories
select categories;
CategoryList.DataSource = result;
CategoryList.DataBind();
}
}
I want the sub category have an indent by add a <td> tag to the item which "ParentId" is not null. And my question is how to edit the generated html tags in the ItemDataBound event?
You could have something like this:
<ItemTemplate>
<tr>
<td colspan="2"><%# GetParentContent(Eval("ParentID")) %></td>
</tr>
</ItemTemplate>
in the code-behind:
protected string GetParentContent(object ParentID)
{
if(ParentID!=null)
... return parent HTML ...
else
return "";
}

Resources