Change the source of image by clicking thumbnail using updatePanel - asp.net

For example, i have this ImageViewer.ascx UserControl:
<div class="ImageTumbnails">
<asp:ListView ID="ImageList" runat="server" ItemPlaceholderID="ItemContainer">
<LayoutTemplate>
<asp:PlaceHolder ID="ItemContainer" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<asp:HyperLink runat="server"
NavigateUrl='<%# Link.ToProductImage(Eval("ImageFile").ToString())%>'>
<asp:Image runat="server" ImageUrl='<%# Link.ToThumbnail(Eval("ImageFile").ToString()) %>' />
</asp:HyperLink>
</ItemTemplate>
</asp:ListView>
</div>
<div class="ImageBig">
<asp:Image ID="ProductImageBig" runat="server" ImageUrl="" />
</div>
When the thumbnail is clicked it will change the source of ProductImageBig with its hyperlink target.
How can i achieve this using UpdatePanel ? ( Or will i be able to )

You are currently using a HyperLink control which will direct the user to the value of the NavigateUrl property. If it goes to a separate page, how will it modify the URL of the ProductImageBig control?
One option is to change the HyperLink control to a ImageButton and then specify a method in your codebehind for the "OnCommand" property.
In the code behind, you can cast the sender object to a the ImageButton, retrieve its ImageURL, and then set the URL of your ProductImageBig
public void DisplayPhoto(object sender, CommandEventArgs args)
{
ProductImageBig.NavigateUrl = ((ImageButton)sender).ImageUrl;
updatePanel.Update();
}
If you have the entire markup surrounded in an UpdatePanel named "updatePanel" and you have the properties set correctly, you can then update it after setting the Url.

Related

Binding ListView Field to Value in Code-Behind

I'm displaying fields from a DB call in a ListView. I had to re-code my database query because of an issue with repeating groups. I also didn't want to have to deal with nested ListViews. So now I am trying to set the header to the value of radio button list selection. I was trying to write a custom method to return that value but could not remember the syntax.
How can I set the header in the LayoutTemplate from the code-behind so that it doesn't repeat?
<LayoutTemplate>
<div class="resultsGrid">
<strong><%# GetHeader() %></strong>
<asp:PlaceHolder runat="server" ID="resultsPlaceHolder">
</asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
// rest of data
</ItemTemplate>
I was able to solve this as follows:
<asp:ListView ID="resultsList" ItemPlaceholderID="resultsPlaceHolder"
OnItemCreated="ResultsList_ItemCreated" runat="server">
<LayoutTemplate>
<div class="resultsGrid">
<strong><asp:Label ID="headerLabel" runat="server"></asp:Label></strong>
<asp:PlaceHolder runat="server" ID="resultsPlaceHolder">
</asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
// rest of data
</ItemTemplate>
</asp:ListView>
And in the code-behind:
protected void ResultsList_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewItem)
{
Label tempLabel = resultsList.FindControl("headerLabel") as Label;
tempLabel.Text = ViewState["ParkName"].ToString();
}
}

Passing CommandArguement to LinkButton from variable

I have seen many resources on SO that say that I can use following syntax to pass value to CommandArguement of `LinkButton'
<%forearch(var comment in Comments){%>
<asp:LinkButton ID="del" CommandArguement='<%= comment.CommentId%>' onCommand="delete_click" Text="Delete"/>
<%}%>
But when I write this in my ascx file and click on the link the value passed to command argument is "<%=comment.CommentId%>" instead of commentId itself. Please guide what am I doing wrong?
Edit 1
based on answers and comments, I have moved to use repeater instead of foreach and plain code. Here is the code I have come up with
<asp:Repeater ID="commRepeater" SelectMethod="GetPageComments" runat="server">
<ItemTemplate>
<p>
<%#Eval("Comment") %>
<%if(Page.User.Identity.IsAuthenticated && Page.User.Identity.GetUserId() == Eval("UserId")){ %>
<span>
<asp:LinkButton Text="Edit" runat="server" ID="EditLink" CommandArgument='<%#Eval("CommentId")%>' OnClick="Update_Comment" />
<asp:LinkButton Text="Delete" runat="server" ID="DeleteLink" CommandArgument='<%#Eval("CommentId")%>' OnClientClick="if (!confirm('Are you sure you want delete?')) return false;" OnCommand="Delete_Comment" />
</span>
<%} %>
</p>
</ItemTemplate> </asp:Repeater>
you can see that I am trying to show the edit and delete links if user is logged in and his Id matches with user who commented but it tells me that I can on use Eval in databound controls. how would I hide/show edit/delete links conditionally within repeater
You could simply use codebehind, for example in Page_Load:
protected void Page_Load(Object sender, EventArgs e)
{
if(!IsPostBack)
{
del.CommandArgument = comment.CommentId;
}
}
Maybe a better approach would be to use the Comments-collection(which seems to be a list or array of a custom class) as DataSource of a Repeater(or other web-databound control). Then you can add the LinkButtons to the Itemtemplate.
You can then either use ItemCreated or ItemDataBound events of the repeater in codebehind or inline ASP.NET tags to bind the CommandArgument.
For example:
CommandArguement='<%# DataBinder.Eval( Container.DataItem, "CommentId" ) %>'
What you are doing currently is not recommended and is highly error prone. You can easily achieve this with ASP.NET Repeater control like this:-
<asp:Repeater ID="MyRepeater" runat="server">
<ItemTemplate>
<asp:LinkButton ID="del" CommandArguement='<%# Eval("CommentId") %>'
OnCommand="del_Command" Text="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
In Page_Load simply bind it:-
if (!Page.IsPostBack)
{
MyRepeater.DataSource = CommentsRepository();
MyRepeater.DataBind();
}
Or Else if you are have ASP.NET 4.5 then use strongly type Data Bound controls like this:-
<asp:Repeater ID="MyRepeater" runat="server" ItemType="MyNamespace.Comment"
SelectMethod="MyRepeater_GetData">
<ItemTemplate>
<asp:LinkButton ID="del" CommandArguement='<%# Item.CommentId %>'
OnCommand="del_Command" Text="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
And you method in code behind should be something like this(just for Demo):-
public IEnumerable<MyNamespace.Comment> MyRepeater_GetData()
{
return new List<Comment>
{
new Comment { CommentId =1, Name= "foo"},
new Comment { CommentId =2, Name= "bar"},
};
}

asp.net ajax like reorder list

I'm trying to create a draggable list to change the order some pictures are displayed in a product page. I wan't to be able to do this in the product edit page (same place where I add the pics and their description). So, when creating I have nothing inserted on the database and since the AJAX toolkit reorderlist only works with a datasource I was specifying the list as the source of the reorderlist and calling the databind method. In the item template of the reorder list I have a textbox to edit the pic description and a img that displays the photo. I can drag the items and the list gets reordered, however when I click save I can't get the updated text on the textbox and the order property on the picture doesn't get updated. I've tried manually getting the items in the reorderlist but they're always null even though the list shows 20 items the DataItem is empty. I've enabled viewstate and didn't help either.
Here's my code:
<ajaxToolkit:ReorderList ID="rdlPhotos" runat="server" SortOrderField="PhotoOrder" AllowReorder="true" PostBackOnReorder="true" ClientIDMode="AutoID" EnableViewState="true" ViewStateMode="Enabled">
<ItemTemplate>
<div>
<%--<eva:PhotoView ID="iPV" runat="server" Photo='<%# Container.DataItem %>' />--%>
<asp:Image ID="imgPhoto" runat="server" ImageUrl='<%# string.Format("http://eva-atelier.net/sparkle{0}", Eval("Path").ToString().Substring(1)) %>' Width="150" Height="150" />
<div class="formGrid">
<label class="formLabel">Title</label>
<asp:TextBox ID="txtTitle" runat="server" Text='<%#Bind("FileTitle") %>' />
<br />
<label class="formLabel">Description</label>
<asp:TextBox ID="txtDescription" runat="server" Text='<%#Bind("FileDescription") %>' />
<br />
</div>
<p>
<asp:Button ID="btnRemove" runat="server" Text="Remover" />
</p>
</div>
</ItemTemplate>
<ReorderTemplate>
<asp:Panel ID="pnlReorder" runat="server" />
</ReorderTemplate>
<DragHandleTemplate>
<div style="width:20px;height:20px;background-color:Red"></div>
</DragHandleTemplate>
</ajaxToolkit:ReorderList>
And below the C# code:
private void AddPhotosView()
{
if (_currentProduct.Photos != null && _currentProduct.Photos.Count > 0)
{
rdlPhotos.DataSource = _currentProduct.Photos;
rdlPhotos.DataBind();
}
}
I'm new to Asp.net I come from a large WPF background, sorry if I'm making basic question :)
Thanks
For updating order of ReorderList items add your handler for it's OnItemReorder event. In this case your handler may looks like this:
protected void ReorderHandler(object sender, ReorderListItemReorderEventArgs e)
{
var movedPhoto = _currentProduct.Photos[e.OldIndex];
_currentProduct.Photos.RemoveAt(e.OldIndex);
_currentProduct.Photos.Insert(e.NewIndex, movedPhoto);
_currentProduct.Photos.Save();
}
For updating FileTitle and FileDescription of single Photo it is easy to use OnUpdateCommand event of ReorderList and a button with attribute CommandName="Update" for each Photo.
And for updating all Photos at once just iterate through rdlPhotos.Items in next manner:
protected void SaveAllHandler(object sender, EventArgs e)
{
foreach (var riItem in rdlPhotos.Items)
{
var id = ((HiddenField)riItem.FindControl("itemID")).Value;
var title = ((TextBox)riItem.FindControl("txtTitle")).Text;
var description = ((TextBox)riItem.FindControl("txtDescription")).Text;
UpdatePhoto(id, title, description);
}
}
Remember that rdlPhotos.Items here are in initial order. And for identifying which Photo should be updated add hidden field with Photo.ID-value to ReorderList's ItemTemplate like this:
<asp:HiddenField runat="server" ID="itemID" Value='<%# Eval("ID") %>' />

User control (ascx) in asp.net and its bindable properties dont show up in the data container

When I add a user control which has bindable properties to an asp.net page I do not see its bindable properties on the designer's dialog box when I click the edit Data bindings on the Repeater-Listview
should I add any other propery descriptors?
the markup would be like this inside a repeater or similar control
<uc1:Menu ID="Menu1" superman="<% Eval("userid") %>" runat="server" />
on the bindable property I only use
[System.ComponentModel.DefaultBindingProperty("superman")]
[System.ComponentModel.Bindable(true)]
public int superman
{
get;
set;
}
People discuss it here but they couldn't find a solution
I think this might be a problem with Visual Studio, I have not found a way to show the properties of user controls, but still, you can bind the property even when it does not appear in the options box:
This is how you bind it:
In the user control code behind:
[Bindable(true)]
public string MyProperty
{
get
{
return this.lblMessage.Text;
}
set
{
this.lblMessage.Text = value + DateTime.Now.ToString();
}
}
In the ASCX file:
<asp:Label ID="lblMessage" Text="something" runat="server" />
In the ASPX page:
<asp:DataList runat="server" ID="dataList" Width="50%"
DataSourceID="ObjectDataSource1">
<ItemTemplate>
<uc1:WebUserControl1 runat="server" ID="myUC" MyProperty='<%# Eval("Name") %>' />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetProducts" TypeName="WebApplication1.Repository">
</asp:ObjectDataSource>
Simple just add the property you created in your UC in the tag:
<uc1:WebUserControl1 runat="server" ID="myUC" MyProperty='<%# Eval("Name") %>' />
This is the output:
I think you just make the markup by typing it,
the user control must be drag and drop to the page in the design view.
try this may helps.

RadioButtonList inside UpdatePanel inside Repeater, Can I?

I have a repeater with a RadioButtonList inside the ItemTemplate, but when the RadioButtonList.OnSelectedIndexChanged event fires it generates a full postback. What have I done wrong in my code below? How can I get the OnSelectedIndexChanged to generate an Async Postback?
<asp:UpdatePanel runat="server" ID="UpdatePanel2">
<ContentTemplate>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="sqlOptions">
<ItemTemplate>
<asp:UpdatePanel runat="server" ID="pnlA">
<ContentTemplate>
<strong>
<%# Eval("Name") %></strong><br />
<asp:RadioButtonList ID="RadioButtonList1"
DataSourceID="sqlOptionValues" runat="server"
DataTextField="id" DataValueField="Id" AutoPostBack="true"
OnSelectedIndexChanged="LoadPrice"
ValidationGroup="options" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ForeColor="Red" runat="server"
ControlToValidate="RadioButtonList1"
ErrorMessage="Required Field"
ValidationGroup="options" />
<asp:SqlDataSource ID="sqlOptionValues" runat="server"
ConnectionString="<%$ ConnectionStrings:
ConnectionString6 %>"
SelectCommand='<%# "SELECT DISTINCT OptionValue.Name,
OptionValue.Id FROM CombinationDetail
INNER JOIN OptionValue
ON CombinationDetail.OptionValueId = OptionValue.Id
WHERE (OptionValue.OptionId =" +
Eval("Id") + ")" %>'>
</asp:SqlDataSource>
<br />
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Many thanks for any help :)
This is a real-world use case. I have a page with Repeaters, Ajax Accordions inside of other Accordions, Update Panels inside other Update panels, you name it. The page works great, except when I want to update one of the Accordion panels with my RadioButtonList (RBL). Even with the RBL inside an update panel, it causes a postback of the entire page. I tried everything. I finally realized it wasn't me when I noticed my buttons would work just fine. I figure it must be a bug in either the framework or the Ajax Control Toolkit. I did find people reference this link all over the web (http://blog.smarx.com/posts/the-case-of-the-radiobuttonlist-half-trigger.aspx), but this link from 2007 is dead now and probably no longer applicable, so that's no help.
What I ended up doing was going with what works - that submit button. All I did was add an onclick attribute to the RBL to call a hidden button. Now you don't want to set the button to Visible=false because then the button won't appear in the generated markup. Instead, set the button's style to display:none; so that no one will see this hack, because yes, that's what this workaround is - it's a hack, but simple and just as effective as what you'd expect. Don't forget to remove the Autopostback="True" from your RBL.
CAVEAT: Because I'm using a hacked button for the onclick event, it's possible for the user to click in the area of the RBL, but not actually select an item. When this happens, our onclick triggers an AsyncPostBack and the codebehind logic will be processed, so please keep that in mind. To give you an idea of what I mean: all the Page_Load() events will be called, but rbl_Questions_SelectedIndexChanged() won't be if they happen to click in the area of the RBL without actually selecting an item. For my purposes this causes no issues in my logic and has no effect on the user.
Here's the Code:
Somewhere In the .Aspx Page:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="rbl_Questions" runat="server"
OnSelectedIndexChanged="rbl_Questions_SelectedIndexChanged">
</asp:RadioButtonList>
<asp:Button ID="btn_rbl_Questions" runat="server" style="display:none;"/>
<asp:Label ID="lbl_Result" runat="server" Text="" Visible="false">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
In the Page_Load() event:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
//Instead of using the AutoPostback of the RBL, use this instead.
rbl_Questions.Attributes.Add("onclick",
"document.getElementById('"
+ btn_rbl_Questions.ClientID
+ "').click();");
//Bind your RBL to a DataSource, add items programmatically,
// or add them in the aspx markup.
}
}
In the rbl_Questions_SelectedIndexChanged() event:
protected void rbl_Questions_SelectedIndexChanged(object sender, EventArgs e)
{
//Your code here.
//My code unhid the lbl_Result control and set its text value.
}
Update 05/24/2011
The above "hack" is no longer necessary (I am leaving it above since this was marked as the answer by the author). I have found the best way to do this, thanks to this SO Answer:
Updatepanel gives full postback instead of asyncpostback
The code is much simpler now, just remove what I put in the Page_Load() method and remove the Button I used in the Aspx page and add ClientIDMode="AutoID" and AutoPostBack="True" to the control you want the UpdatePanel to capture.
Somewhere In the .Aspx Page:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="rbl_Questions" runat="server"
ClientIDMode="AutoID" AutoPostBack="true"
OnSelectedIndexChanged="rbl_Questions_SelectedIndexChanged">
</asp:RadioButtonList>
<asp:Label ID="lbl_Result" runat="server" Text="" Visible="false">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
MS changed how ClientID's are generated in .net 4.0 from "AutoID" to "Predictable" and I guess the ScriptManager or UpdatePanel's weren't updated correctly to use it. I can't find documentation on why that is anywhere or if it was left that way by design.
I seriously don't miss winforms.
Try this:
<asp:UpdatePanel runat="server" UpdateMode="Conditional" ID="pnlA">
You'll also need to setup
<Triggers>
//radio buttons
</Triggers>
Not sure how you'll do that since it's a dynamically built list.

Resources