Error while data binding to grid [duplicate] - c#

This question already has answers here:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control
(4 answers)
Closed 9 years ago.
I have following code in gridview:
<% If Eval("LabelType").ToString() = "Singleline" Then%> <asp:TextBox ID="txtSingleLine" runat="server" ></asp:TextBox> <% End If%>
<% If Eval("LabelType").ToString() = "Multiline" Then%> <asp:TextBox ID="txtMultiline" runat="server" TextMode="MultiLine" ></asp:TextBox> <% End If%>
<% If Eval("LabelType").ToString() = "Image" Then%> <asp:FileUpload ID="FileUpload1" runat="server" /> <% End If%>
I am getting following error:
Databinding methods such as Eval(), XPath(), and Bind() can only be
used in the context of a databound control
From this question i came to know that # should be added, but when i added as:
It was not accepting this (showing blue line below whole statement).
Please tell me where i am making mistake.
Please help me.
I am using vb.net but answer in c# is also helpful.

You could try setting the visibility on each control based on the value of LabelType like so:
<asp:TextBox ID="txtSingleLine" runat="server" Visible="<%# Eval("LabelType").ToString() == "Singleline" %>"></asp:TextBox>
<asp:TextBox ID="txtMultiline" runat="server" TextMode="MultiLine" Visible="<%# Eval("LabelType").ToString() == "Multiline" %>" ></asp:TextBox>
<asp:FileUpload ID="FileUpload1" runat="server" Visible="<%# Eval("LabelType").ToString() == "Image" %>" />

Like the error says you cannot have an Eval outside of data bound control, so I would recommend that you dynamically insert the controls into a PlaceHolder control, like this:
Markup:
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
Code-behind:
If LabelType = "Singleline" Then
' Create textbox and add to placeholder
Dim textbox = New TextBox()
textbox.ID = "txtSingleLine"
PlaceHolder1.Controls.Add(textbox)
Else If LabelType = "Multiline" Then
' Create textbox with multi-line text mode and add to placeholder
Dim multilinetextbox = New TextBox()
multilinetextbox.ID = "txtMultiline"
PlaceHolder1.Controls.Add(multilinetextbox)
Else If LabelType = "Image" Then
' Create file upload and add to placeholder
Dim fileupload = New FileUpload()
fileupload.ID = "FileUpload1"
PlaceHolder1.Controls.Add(fileupload)
End If
Note: LabelType in the code above is the string representation of what you were doing in Eval("LabelType").ToString().

Related

Change Css class on a Panel thats located inside a Asp:repeater

Hello and thanks for taking your time to read this.
I'm trying to change the CSS class of a panel thats located inside a Repeater when I select a RadioButton.
<div>
<asp:RadioButtonList OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged" AutoPostBack="true" ID="RadioButtonList1" RepeatDirection="Horizontal" runat="server">
<asp:ListItem Selected="True">Show Gallery</asp:ListItem>
<asp:ListItem>Show List</asp:ListItem>
</asp:RadioButtonList>
</div>
<div class="RpOutterFrame" runat="server" id="RpOutterFrame">
<asp:Repeater runat="server" ID="RP">
<ItemTemplate>
<panel class="ShowDiv" runat="server" id="RpInnerFrame">
<img runat="server" style="width: 80px;" id="ModelImg" class="ModelImg" src='<%# string.Format("~/Content/Img/ModelImg/{0}", Eval("Image")) %>' />
<br />
<%# Eval("Model") %>
</panel>
</ItemTemplate>
</asp:Repeater>
</div>
My C#:
protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (RadioButtonList1.Items[0].Selected == true)
{
RpOutterFrame.Attributes["class"] = "RpOutterFrame";
Panel panel = (Panel)this.FindControl("RpInnerFrame");
panel.CssClass = "ShowDiv2";
}
}
As you can see the Panel already has the class ShowDiv and then I would like it to change the class to ShowDiv2 when I select/click the Radiobutton.
Anyone who can help me figuar what I'm doing wrong or fix the code?
A Repeater's purpose is to repeat something. So normally it contains multiple elements. Therefore the RepeaterItem is the NamingContainer which must contain unqiue ID's and where you can find your controls via FindControl(ID).
So this does not work since this is the Page which is not the NamingContainer of the Panel:
Panel panel = (Panel)this.FindControl("RpInnerFrame");
panel.CssClass = "ShowDiv2";
You have to loop all items:
foreach(RepeaterItem item in RP.Items)
{
Panel panel = (Panel)item.FindControl("RpInnerFrame");
panel.CssClass = "ShowDiv2";
}
Apart from that you should use the ASP:Panel instead of Panel.
So change
<panel class="ShowDiv" runat="server" id="RpInnerFrame">
// ...
</panel>
to
<ASP:Panel CssClass="ShowDiv" runat="server" id="RpInnerFrame">
// ...
</ASP:Panel>

looping through checkboxes and inserting checkbox values to DB

ASPX Page:
<asp:ListView ID="lvSubjects" runat="server" >
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<asp:CheckBox ID="cbRegularSubjects" Text=<%# Eval("SubjectName") %> runat="server" />
</ItemTemplate>
<AlternatingItemTemplate>
<asp:CheckBox ID="cbRegularSubjects" Text=<%# Eval("SubjectName") %> runat="server" />
</AlternatingItemTemplate>
</asp:ListView>
Code Behind:
For Each ctrl As Control In Page.Controls
If TypeOf ctrl Is CheckBox AndAlso CType(ctrl, CheckBox).Checked Then
'**Here I want to get the text of the check box and insert into the DB**
End If
Next
Where am i going wrong??i do not get any error...but this code is not working for me.
For i As Integer = 0 To lvSubjects.Items.Count - 1
Dim coll As ControlCollection = lvSubjects.Items(i).Controls
For Each c As Control In coll
If TypeOf c Is CheckBox Then
Dim box As CheckBox = CType(c, CheckBox)
If box.Checked Then
MsgBox(box.Text)
End If
End If
Next c
Next i
you are only searching in Page.Controls whereas your checkboxes are inside deeper in page control hierarichy.
foreach (ListViewItem row in listView.Rows)
{
if (row.ItemType == ListViewItemType.DataItem)
{
CheckBox chk = row.FindControl("Checkboxid");
if (chk.Checked)
{
//Write code to store this checkbox value to database here
}
}
}
Please change the code in VB with proper control name

Change value of label and hide imagebutton in asp repeater

I've an asp repeater which has some fields inside an ItemTemplate. Each item in the repeater has an "add to cart" asp:ImageButton and an invisible asp:Label as well. The code looks like this:
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="addToCart">
<HeaderTemplate>
<table id="displayTable">
</HeaderTemplate>
<ItemTemplate>
<td>
<!-- fields like name, description etc in the repeater are present; i've omitted to show them here-->
<asp:Label ID="addedToCartLabel" runat="server" Visible="false"></asp:Label>
<asp:ImageButton ID="addToCartImg" runat="server" ImageUrl="hi.jpg" Width="75px" Height="50px" />
</td>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
When a particular ImageButton in the repeater is clicked, I'm trying to display "added to cart" as the text of its corresponding Label, and make the clicked ImageButton Visible=false. I've tried using the OnItemCommand function for the ASP:Repeater. The method is "addToCart":
<>
void addToCart(Object Sender, RepeaterCommandEventArgs e)
{
Cart cart = new Cart();
cart.instrument_id = //id of product from repeater based on user click
String userName = Membership.GetUser().ToString();
cart.user_name = userName;
cart.quantity = 1;
var thisLbl = (Label)e.Item.FindControl("addedToCartLabel");
var thisImg = (ImageButton)e.Item.FindControl("addToCartImg");
try
{
database.Carts.InsertOnSubmit(cart);
database.SubmitChanges();
thisImg.Visible = false;
thisLbl.Text = "Added to Cart!";
thisLbl.Visible = true;
}
catch (Exception ex)
{
thisImg.Visible = false;
thisLbl.Text = "Processing failed;please try again later";
thisLbl.Visible = true; ;
}
}
The aspx page is populated properly. However, when I click on any of the ImageButtons in the repeater, I get the following error:
Server Error in '/mysite' Application.
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%# Page EnableEventValidation="true" %> in a page.
For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.
If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback
or callback data for validation.
Can someone help me with this?
May I suggest doing this with client-side javascript rather than a server-side call?
<asp:Label ID="addedToCartLabel" runat="server" Visible="false"></asp:Label>
<asp:ImageButton ID="addToCartImg" runat="server" ImageUrl="hi.jpg" Width="75px" Height="50px" />
becomes
<asp:Label ID="addedToCartLabel" runat="server" Visible="false"></asp:Label>
<asp:ImageButton ID="addToCartImg" runat="server" onclick="javascript:function() { this.this.style.display='none'; document.getElementById(this.parentNode.firstChild.id).style.display='block'; }" ImageUrl="hi.jpg" Width="75px" Height="50px" />

How to wrap image in <a></a> based on condition in asp.net repeater?

Lets say I have a data table with the columns ImageUrl, Text, LinkUrl and Title.
I databind this to a repeater and displays everything without any issue. However, LinkUrl can be empty and then I want the code to be like the one below. If the LinkUrl contains a string/link then I want to wrap the image with a link to the URL. Please ask questions if I need to clarify more.
Example code:
<asp:Repeater runat="server" ID="rptImageGallery">
<ItemTemplate>
<div class="slide">
<asp:Image ID="Image1" runat="server" ImageUrl='<%#UrlHelper(DataBinder.Eval(Container.DataItem, "ImageUrl"))%>'>
<h2><%# DataBinder.Eval(Container.DataItem, "Title") %></h2>
<p><%# DataBinder.Eval(Container.DataItem, "Text")%></p>
</div>
</ItemTemplate>
</asp:Repeater>
Code behind:
DataTable dt = new DataTable();
dt = collListItems.GetDataTable().AsEnumerable()
.Where(a => Convert.ToString(a["Published"]) == "1")
.CopyToDataTable();
rptImageGallery.DataSource = dt;
rptImageGallery.DataBind();
So if the current row contains a link in LikUrl then I want the repeater to present something like this
<asp:Repeater runat="server" ID="rptImageGallery">
<ItemTemplate>
<div class="slide">
<asp:Image ID="Image1" runat="server" ImageUrl='<%# UrlHelper(DataBinder.Eval(Container.DataItem, "FileLeafRef"))%>' />
<%# DataBinder.Eval(Container.DataItem, "Title") %></h2>
<p><%# DataBinder.Eval(Container.DataItem, "Text")%></p>
</div>
</ItemTemplate>
</asp:Repeater>
Any suggestions on how to achieve this?
Edit: something weird with the post. When I go Edit I can see the correct code - slick Save and it doesn't update my code example. Anyway, in the last code part I want a link wrapping the image or image text.
try this:
<asp:Repeater ID="rpt1" runat="server">
<ItemTemplate>
<div class="slide">
<asp:Image ID="img1" runat="server" ImageUrl='<%#GetUrl(Eval("Image"))%>'/>
<%# WrapTitle(Eval("Title"), Eval("Link"))%>
</div>
</ItemTemplate>
</asp:Repeater>
code behind (I have added complete code so that you can test):
Public Class Repeater
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim dt As DataTable = New DataItem().GetData()
rpt1.DataSource = dt
rpt1.DataBind()
End If
End Sub
Protected Function WrapTitle(ByVal title As Object, ByVal lnk As Object) As String
If Not String.IsNullOrWhiteSpace(lnk.ToString()) Then
Return String.Format("<a href='{0}'>{1}</a>", lnk, title)
End If
Return title.ToString()
End Function
Protected Function GetUrl(ByVal img As String) As String
Return Page.ResolveUrl("~/Images/") + img
End Function
End Class
Public Class DataItem
Private lnks() As String = {"http://www.google.com", "http://www.yahoo.com", "http://www.bing.com", "http://www.superuser.com", "http://www.stackoverflow.com", ""}
Private titles() As String = {"Google", "Yahoo", "Bing", "superuser", "stackoverflow", "ask.com"}
Private images() As String = {"nav_logo91.png", "yahoo.png", "bing.png", "superuser.png", "stackoverflow.png", ""}
Public Function GetData() As DataTable
Dim dtb As New DataTable
dtb.Columns.Add("title")
dtb.Columns.Add("link")
dtb.Columns.Add("Image")
For i As Integer = 0 To titles.Length - 1
dtb.Rows.Add(New Object() {titles(i), lnks(i), images(i)})
Next
Return dtb
End Function
End Class
PS:- probably you will not need GetUrl function.

AJAX ToolKit TabContainer: Can I capture the "Active Tab Panel Changing" event

I have an AJAX ToolKit TabContainer control with several TabPanels. I want to validate the contents of the current active TabPanel to prevent user from working on other ones in case data was invalid.
If you need to do a TabPanelChangingEvent SERVER side, You will need to do this by Altering the ajaxcontroltoolkit Source code.
Good news : you could easily get it
Here a new solution that does almost what your need :
The OnClientActiveTabChanged event is raised
The tabcontainer New Tab index is saved in a Hiddenfield
The tabindex is reset to it's old value (so it wont change right now)
The form trigger a asyncpostback using a hidden button.
Within the hidden button's Click event, the OldTabIndex and NewTabIndex are retrieved.
At the end of the Click event, the tabcontainer's tabindex is switched to the new value.
So, the hidden button's Click event is executed before the TabContainer tab is changed.
aspx:
<asp:Button runat="server" ID="hiddenTargetControlForTabContainer" style="display:none" />
<asp:UpdatePanel ID="TabContainerUpdatePanel" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="hiddenTargetControlForTabContainer" />
</Triggers>
<ContentTemplate>
<asp:HiddenField ID="TabContainerActiveTab" runat="server" Value="0" />
<AjaxControlToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0"
OnClientActiveTabChanged="OrderTabContainerClientActiveTabChanged" >
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel1"
HeaderText="TabPanel1"
>
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel2"
HeaderText="TabPanel2" >
<ContentTemplate>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
</AjaxControlToolkit:TabContainer>
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
var TabContainerActiveTabControlID = '<%= TabContainerActiveTab.ClientID %>';
var hiddenTargetControlForTabContainerControlID = '<%= hiddenTargetControlForTabContainer.uniqueID %>';
function OrderTabContainerClientActiveTabChanged(sender, args) {
var TabContainerActiveTabControl = $get(TabContainerActiveTabControlID);
var OldtabIndex = parseInt(TabContainerActiveTabControl.value);
var NewtabIndex = sender.get_activeTabIndex();
if (!(OldtabIndex == NewtabIndex)) {
sender.set_activeTabIndex(OldtabIndex);
TabContainerActiveTabControl.value = NewtabIndex;
__doPostBack(hiddenTargetControlForTabContainerControlID, '');
}
}
Code behind:
Protected Sub hiddenTargetControlForTabContainer_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles hiddenTargetControlForTabContainer.Click
Dim oldActiveTabIndex = TabContainer1.ActiveTabIndex
Dim newActiveTabIndex As Integer = Convert.ToInt32(TabContainerActiveTab.Value)
'your stuff here
TabContainer1.ActiveTabIndex = newActiveTabIndex
End Sub
Problem: Ajax TabContainer the ActiveTabChanged event shows incorrect ActiveTabIndex.
For eg. TabContainer contain 3 tabs, if second tab is hide(visible = false on server side) then on click of third tab, we get ActiveTabChanged = 1 not 2 (expected active index is 2 on server side code).
Solution:
Register the clientside event of the tab container:
OnClientActiveTabChanged="Tab_SelectionChanged"
Then define the javascript function to handle the above event which will internally store the tab index in a hidden variable.
function Tab_SelectionChanged(sender,e)
{
document.getElementById('<%=hdntabIndex.ClientID %>').value = sender.get_activeTabIndex();
}
Use the hidden variable(hdntabIndex) in the code behind where ever you need the active tab index.
You should do it using JavaScript.
Here an example I made, the trick is to use ValidationGroup and save the Old tab Index at the end of the function called by the OnClientActiveTabChanged
<AjaxControlToolkit:TabContainer ID="TabContainer1" runat="server" Height="138px"
Width="402px" ActiveTabIndex="0"
OnClientActiveTabChanged="ValidateTab" >
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel1"
HeaderText="TabPanel1"
>
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="RequiredFieldValidator"
ControlToValidate="TextBox1"
ValidationGroup="TabPanel1"
/>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel2"
HeaderText="TabPanel2" >
<ContentTemplate>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
ErrorMessage="RequiredFieldValidator"
ControlToValidate="TextBox2"
ValidationGroup="TabPanel2"
/>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
</AjaxControlToolkit:TabContainer>
<script type="text/javascript">
var OldtabIndex = 0;
function ValidateTab(sender, args) {
if (OldtabIndex == 0) {
if (!Page_ClientValidate('TabPanel1')) {
sender.set_activeTabIndex(OldtabIndex);
}
}
else if (OldtabIndex == 1) {
if (!Page_ClientValidate('TabPanel2')) {
sender.set_activeTabIndex(OldtabIndex);
}
}
OldtabIndex = sender.get_activeTabIndex();
}
</Script>
I know I'm probably late to answering this question, but hopefully, I can offer some assistance to someone who's pot-committed like I was to the TabPanels.
Add the OnClientActiveTabChanged="showMap" to the ajaxToolkit:TabContainer. My function is obviously called showMap (had to hide and show the Google Street Map, because TabContainer screws it all up. So I had to move the Google Street Map outside of the container and then 'fake' put it back in the container).
<ajaxToolkit:TabContainer runat="server" ID="tabs" OnClientActiveTabChanged="showMap">
<ajaxToolkit:TabPanel runat="server" ID="pnlZones" HeaderText="Delivery Zones">
<ContentTemplate>
...
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
Then create the javascript:
<script type="text/javascript">
function showMap() {
var tabID = $('.ajax__tab_active').attr('id');
if (tabID.indexOf('pnlZone') > 0) {
$('#mapHider').css('height', '600px');
}
else {
$('#mapHider').css('height', '0');
}
}
</script>
We can then find the active tab by the class .ajax__tab active, which is what TabContainer will set the active class to. Snag the ID (.attr('id')) with jQuery... And voila, we now which tab we're currently on.
For this I change the height of the class from 0 to 600px. With the overflow set to hidden, it makes it seem like the map is on the page and only in that container, but it isn't.
Hopefully, this helps!! Good luck.

Categories

Resources