I have control configured as below. control is populated from server without postback to server but after I make postback i can't get checked items. Is there any solution for this or maby there is other idea.
Main issue is to populate treeview without full page postback.
Thx for any help.
<asp:TreeView ShowLines="True" runat="server" ID="trvCategories" ShowCheckBoxes="All" EnableClientScript="True" PopulateNodesFromClient="True" OnTreeNodePopulate="PopulateNode">
</asp:TreeView>
I did something like this in my VB.NET application; it may very well work in ASP.NET also.
Private Sub tvwDataCategory_AfterCheck(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.TreeViewEventArgs) Handles tvwDataCategory.AfterCheck
Dim Node As System.Windows.Forms.TreeNode = eventArgs.Node
Dim n As Integer
If VB.Left(Node.Name, cTagLength) = cDataTypeTag Then
Node.ForeColor = DefaultForeColor
Dim nNodes As TreeNodeCollection = eventArgs.Node.Nodes
For Each nNode As TreeNode In nNodes
If nNodes.Count = 0 Then
If nNode.Checked Then
tvwDataCategory.Nodes.Item(n).Checked = True
Else
tvwDataCategory.Nodes.Item(n).Checked = False
End If
End If
Next
Else
Call FormatChecks()
End If
End Sub
Is this what you're looking for?
Related
I have an asp.net Visual Basic web site, and I am using a stored procedure to get values to populate a drop-down list.
However, I have two issues. If I put the method to fill the drop-down list within my If Not IsPostBack statement in the page load event, then the whole list is filled with items saying 'System.Data.DataViewRow' instead of the actual values. If I put it outside this 'if' statement but still in my page load event, I get the correct values, but no matter what I select, when I leave the drop-down it reverts back to the top item instead of the selected item.
What am I doing wrong??
Edit: I have now added the DataTextField as suggested by Nic and put the method inside my 'If Not IsPostBack' event as suggested by Lee Bailey. However, my drop-down is still showing all values as 'System.Data.DataViewRow' so I don't know if Lee's solution has worked or not! Any other ideas on the issue of showing the values! I have updated my code below to reflect the changes.
The visual basic:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
bodyPanel.Visible = False
drpRegion_fill()
End If
End Sub
Protected Sub drpRegion_fill()
Dim sqlConn As SqlConnection
sqlConn = New SqlConnection
sqlConn.ConnectionString = ConfigurationManager.ConnectionStrings("ConnString").ConnectionString
Dim drpRegionCmd As SqlCommand
drpRegionCmd = New SqlCommand("getRegionName", sqlConn)
drpRegionCmd.CommandType = CommandType.StoredProcedure
Dim drpRegionAdp As SqlDataAdapter
drpRegionAdp = New SqlDataAdapter(drpRegionCmd)
Dim drpRegionDs As DataSet
drpRegionDs = New DataSet
sqlConn.Open()
drpRegionAdp.Fill(drpRegionDs)
With drpRegion
.DataSource = drpRegionDs
.DataBind()
.DataValueField = "regionName"
.DataTextField = "regionName"
.SelectedIndex = 0
End With
sqlConn.Close()
End Sub
The markup:
<asp:Panel ID="panelRegion" runat="server" Height="160px" Width="71%" CssClass="inlineBlock">
<h2>Region:</h2>
<asp:dropDownList runat="server" AutoPostBack="true" ID="drpRegion" />
</asp:Panel>
The SQL procedure returns a two-column dataset with 'regionID' as column 1, and 'regionName' as column2.
I've spent about two days on this now, trying various things and reading all the books I can! I have never had this issue in C# when I have performed the same operation and I cannot for the life of me think what I've missed in the VB...
It does not look as though you are setting the DataTextField property of your DropDownList:
With drpRegion
.DataSource = drpRegionDs
.DataValueField = "regionName"
.DataTextField = "fieldToDisplayAsText"
.SelectedIndex = 0
.DataBind()
End With
source:
MSDN DataTextField
It's reverting back to the original value because you are re-binding the values to the dropdown after a postback. Changing the selected item is triggering a postback because you have the AutoPostBack property set to true. I would call drpRegion_fill() only if it's not a postback. Setting the DataTextField as Ric mentioned should solve the problem regarding 'System.Data.DataViewRow'
I'm adding in asp.net (vb) an attribute to an image-button:
imgButton.Attributes.Add("myAttr", "true")
This is working fine.
Now i want to read the attribute, but it does not work:
If imgButton.Attributes("myAttr") = "true" Then
..doSomething..
How do I get this thing working?
Edit
I have an asp.net repeater.
In this repeater i have in each itemtemplate two image buttons.
If I'm clicking on an imagebutton, the other imagebutton in this row changes it's URL.
I want that this URL is saved, after clicking on another row's imagebutton.
So I'm adding in the repeater event
ItemCommand
Dim imgButton As ImageButton
If e.CommandName = "imgBtn1" Then
imgButton = CType(e.Item.FindControl("imgBtn1"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true")
ElseIf e.CommandName = "imgBtn2" Then
imgButton = CType(e.Item.FindControl("imgBtn2"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr2", "true")
End If
In the Page Load event I'm adding:
If Page.IsPostBack Then
Dim countRepeaterItems As Integer = myRepeater.Items.Count
Dim imgButton As ImageButton
For i As Integer = 0 To countRepeaterItems - 1
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn1"), ImageButton)
If imgButton.Attributes.Item("myAttr1") = "true" Then
imgButton.ImageUrl = "myURL"
End If
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn2"), ImageButton)
If imgButton.Attributes.Item("myAttr2") = "true" Then
imgButton.ImageUrl = "myURL"
End If
Next
End If
While debugging, it still skips everything, because all Attributes are empty (but actually they are not)!
Looks like for VB it should be:
If imgButton.Attributes.Item("myAttr") = "true" Then
EDIT: original answer was for C#:
Should be square brackets on the reads:
If imgButton.Attributes["myAttr"] = "true" Then
http://msdn.microsoft.com/en-us/library/kkeesb2c.aspx#Y0
I guess! May be you have (turn off the viewstate) set EnableViewState=False to the imgButton.
Take a look at this sample:
Markup:
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
Code:
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
If Label1.Attributes("myAttr") = "true" Then
Label1.Attributes.Add("myAttr", "false")
Label1.Text = "false is set"
Else
Label1.Attributes.Add("myAttr", "true")
Label1.Text = "true is set"
End If
End Sub
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Label1.Attributes.Add("myAttr", "true")
End If
End Sub
EDIT:
May be typo in ItemCommand event code.
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true") '<----- Correction
Addressing the issue of not finding the attributes set in your page load.
I am not entirely clear on what you are trying to accomplish, but it seems likely that you are running into a problem with the order that events execute. On a post back, the page load event executes, then the event handler for the control causing the post back. If your image button causes the post back, then the attribute is not being set until after the page load event has already completed. However, assuming you are using viewstate, your attribute should be persisted and detected on the following post back.
If this is what is happening to you, then one possible way around it would be to move the code from your page load event to the page pre render event. Pre render occurs after the control's post back events have been handled, and it is one of the last points where you can hook in and make changes to your content before it is committed to viewstate.
I am learning asp.net and needed to have a CheckBoxList which items will be initially selected if the are in a CSV string from a database.
I have got it working although I just wondered if I have gone about it the best way as it seemed a little long winded?
Thanks for any help provided.
ASPX
<asp:CheckBoxList ID="rh_type" runat="server" CssClass="chkbox"
RepeatLayout="Flow" CausesValidation="True">
<asp:ListItem>House</asp:ListItem>
<asp:ListItem>Flat/Apartment</asp:ListItem>
<asp:ListItem>Bungalow</asp:ListItem>
<asp:ListItem>Any</asp:ListItem>
</asp:CheckBoxList>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
CODE
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim i As Integer
Dim str_rh_type As String = "House,Bungalow"
Dim split As String() = str_rh_type.Split(","c)
For Each s As String In split
'Response.Write(s & "<br />")
For i = 0 To rh_type.Items.Count - 1
If rh_type.Items(i).Text = s Then
rh_type.Items(i).Selected = True
End If
Next
Next s
End Sub
Thanks again
J.
Your code is functional but maybe some tweaking for maintainability would help. Also not sure you necessarily need nested loops to load your drop down items.
This should be just a reference point to make your own decisions on coding practices. Certainly what works for some doesn't work for others.
Here's how I'd code this...
ASP.NET Control:
<asp:CheckBoxList ID="CheckBoxListHomeType" runat="server"
CssClass="chkbox" RepeatLayout="Flow" CausesValidation="True" />
...
ID of CheckBoxListHomeType is easy to remember and intellisense will get me the rest of the way. (or another common approach would be cblHomeType as the ID). Getting intellisense to help on a name like rh_type may be just as easy but IDs that resemble what kind of control it is can really help when maintaining code
VB.NET:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
LoadHomeTypes()
End If
End Sub
Protected Sub LoadHomeTypes()
Dim houseTypes = "House,Bungalow,Flat/Apartment,Any"
For Each houseType As String In houseTypes.Split(",")
CheckBoxListHomeType.Items.Add(New ListItem(houseType))
Next
End Sub
Keeping the logic in a separate LoadHomeTypes function can make the code more readable.
Creating a new ListItem while iterating the list of homeTypes should remove the need to iterate over the CheckBoxList items, (if you need to clear out the existing ones you can add CheckBoxListHomeType.Items.Clear() to the top of the function)
the Not Page.IsPostBack check prevents the need for loading the drop down values every postback, unless you have need for them to change.
This is the good answers , try this
Dim ds As DataSet
ds = Insertstu.searchrec(txtsearch.Text)
txtnm.Text = ds.Tables(0).Rows(0)("stuname").ToString()
txtadd.Text = ds.Tables(0).Rows(0)("stuaddress").ToString()
txtph.Text = ds.Tables(0).Rows(0)("stuph").ToString()
rdobtnsex.Text = ds.Tables(0).Rows(0)("sex").ToString()
Dim arr As String()
Dim quali As String = ds.Tables(0).Rows(0)("qualified").ToString()
arr = quali.Split(",")
Dim i As Integer
For Each itm As String In arr
For i = 0 To chkqualify.Items.Count - 1
If chkqualify.Items(i).Text = itm Then
chkqualify.Items(i).Selected = True
End If
Next
Next
''chkqualify is checkboxlist id
Classic scenario: Take user input, get a search-result and display it in pages to the user. I then need to display buttons for First, Next, Previous etc, and I maintain the users current page in viewstate. All is good, works fine.
Then I need to implement clickable page numbers, ie. 1-2-3-4-5-6 etc.
Rendering them is simple. I generate a linkbutton control at runtime, add commandargument with the page number and add a handler to it, so click are to be handled. Then I add it to a placeholder, and it is displayed as expected.
But then... If I did not already have a shaved head, I would be pulling out my hair getting the events to fire as expected every time.
How should I do this, so my events are always wired up and able to fire when the paging-linkbuttons are called?
Below is the important parts of the code, some pseudo to make it (hopefully) easier to understand, what I am doing.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Search()
End If
End Sub
Sub Search
'Misc databinding stuff, searches and displays results for the page specified in Me.CurrentPage
RenderPagingControls()
End Sub
Sub RenderPagingControls
'loop throug pagenumbers, Build a linkbutton control, add it to a placeholder
AddHandler lbn.Click, AddressOf lbnNumber_Click
lblPageNumbers.Controls.Add(lbn)
...
End Sub
Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim b As LinkButton = CType(sender, LinkButton)
Me.CurrentPage = CInt(b.CommandArgument)
Search()
End Sub
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.ViewState("CurrentPage")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("CurrentPage") = value
End Set
End Property
Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim b As LinkButton = CType(sender, LinkButton)
Me.CurrentPage = CInt(b.CommandArgument)
Search()
End Sub
I'm going to recommend against a LinkButton and recommend Hyperlinks / QueryString parameters instead. For several reasons:
Your page will be much more efficient without the viewstate overhead of a link button.
If these are public facing pages, you'll get better indexing of all the pages if they can be accessed via hyperlinks (and indexed via search engines).
You'll find them much easier to implement. No event management, etc.
You would redefine your CurrentPage method as (hopefully this is correct, I'm better at C# than vb.net):
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.Request.QueryString("page")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
End Property
Then just add hyperlinks for each page.
<a href='mypage.aspx?page=1'>1</a> - <a href='mypage.aspx?page=2'>2</a>
etc...
Alternative: If you want to use the LinkButton, you might want to consider putting a single LinkButton in a repeater. Then the only event you have to worry about is the OnItemCommand event. Then no dynamic controls or events. Something like this:
<asp:Repeater ID="rptPages" runat="server" OnItemCommand='doPaging'>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" Text='<%# (Container.DataItem).ToString() %>'
CommandArgument='<%# (Container.DataItem).ToString() %>' />
</ItemTemplate>
<SeparatorTemplate>-</SeparatorTemplate>
</asp:Repeater>
Bind this control to an array (or list) of consecutive Integers (as many are there are pages). Then in your doPaging function (as I call it), check RepeaterCommandEventArgs.CommandArgument to get the page number.
Thanks for the answers, guys. I tried out Austins first, but I must be missing something, because I keep getting the same behavior of link buttons only working every second time... So I gave up on that, and saw the alternative solution with the repeater by Keltex! It is as brilliant as it is simple, and we don't have to worry about any page life-cycle bullshit.
It just really works! ;)
If somebody should need something similar in the future, here is the relevant code behind the scenes:
Sub Search()
...
RenderPagingControls()
End Sub
Sub RenderPagingControls()
Dim pages As New ArrayList
For i As Integer = 1 To Me.PageCount
pages.Add(i)
Next
repPageNumbersTop.DataSource = pages
repPageNumbersTop.DataBind()
repPageNumbersBottom.DataSource = pages
repPageNumbersBottom.DataBind()
End Sub
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.ViewState("CurrentPage")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("CurrentPage") = value
End Set
End Property
Public Property PageCount() As Integer
Get
Dim o As Object = Me.ViewState("PageCount")
If o Is Nothing Then
Return 0
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("PageCount") = value
End Set
End Property
Protected Sub repPageNumbersTop_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles repPageNumbersTop.ItemCommand, repPageNumbersBottom.ItemCommand
Me.CurrentPage = CType(e.CommandArgument, Integer)
Search()
End Sub
Private Sub repPageNumbersTop_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repPageNumbersTop.ItemDataBound, repPageNumbersBottom.ItemDataBound
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
Dim lbn As LinkButton = CType(e.Item.FindControl("lbnPageNumber"), LinkButton)
If lbn.CommandArgument = Me.CurrentPage.ToString Then
lbn.Enabled = False
End If
End If
End Sub
This code works (sorry it's in C#):
protected void SearchButton_Click(object sender, EventArgs e)
{
//clear the collection!
pnlPageNumber.Controls.Clear();
//simulate search
System.Random rnd = new Random();
//create page buttons
for (int i = 0; i < rnd.Next(3, 15); i++)
{
LinkButton lb = new LinkButton();
pnlPageNumber.Controls.Add(lb);
lb.ID = "btn" + i;
lb.Text = i.ToString();
lb.CommandArgument = i.ToString();
lb.Command += new CommandEventHandler(linkbutton_Command);
//optional literal
pnlPageNumber.Controls.Add(new LiteralControl(" "));
}
ViewState["control#"] = Panel1.Controls.Count;
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
//Recreate link buttons
//This is necessary to ensure proper event binding
int count = 0;
if (ViewState["control#"] != null)
count = (int)ViewState["control#"];
for (int i = 0; i < count; i++)
{
LinkButton lb = new LinkButton();
pnlPageNumber.Controls.Add(lb);
lb.ID = "btn" + i; //make sure IDs are the same here and on Search
lb.Command += new CommandEventHandler(linkbutton_Command);
//this is not necessary, but if you do, make sure its in both places
pnlPageNumber.Controls.Add(new LiteralControl(" "));
}
}
}
void linkbutton_Command(object sender, CommandEventArgs e)
{
Response.Write(e.CommandArgument.ToString() + " CLICK<br />");
}
You could use the DataPager control -- the only limitation is you have to use it with the ListView control, but you should be able to represent your data using the ListView control fairly easily because it is very flexible. You can set the DataSource of the ListView control to the result of your data result, whether that be a DataSet, Collection, Array, etc.
To create the paging controls with "first", "last", and page numbers, set up the DataPager like this (where ListView1 is the ID of your ListView control):
<asp:DataPager ID="DataPager1" runat="server"
PagedControlID="ListView1" PageSize="25">
<Fields>
<asp:NextPreviousPagerField FirstPageText="first" ShowFirstPageButton="True"
ShowNextPageButton="False" ShowPreviousPageButton="False" />
<asp:NumericPagerField />
<asp:NextPreviousPagerField LastPageText="last" ShowLastPageButton="True"
ShowNextPageButton="False" ShowPreviousPageButton="False" />
</Fields>
</asp:DataPager>
By design, the DataPager uses the whole result set from the database, but you can improve the performance by caching the result and using that on the subsequent requests.
Hope this helps.
iirc... adding controls dynamically at runtime is a bit tricky. The control tree must be rebuilt during post back... but before viewstate is loaded (not sure when in the page life cycle... but way before page load). So... your problem is that by the time asp.net is trying to figure out your event the actual originating control has not yet been created.
I'm working on an ASP.NET website where I am using an asp:repeater with paging done through a VB.NET code-behind file. I'm having trouble with the database connection though. As far as I can tell, the paging is working, but I can't get the data to be certain.
The database is a Microsoft Access database. The function that should be accessing the database is:
Dim pagedData As New PagedDataSource
Sub Page_Load(ByVal obj As Object, ByVal e As EventArgs)
doPaging()
End Sub
Function getTheData() As DataTable
Dim DS As New DataSet()
Dim strConnect As New OleDbConnection("Provider = Microsoft.Jet.OLEDB.4.0;Data Source=App_Data/ArtDatabase.mdb")
Dim objOleDBAdapter As New OleDbDataAdapter("SELECT ArtID, FileLocation, Title, UserName, ArtDate FROM Art ORDER BY Art.ArtDate DESC", strConnect)
objOleDBAdapter.Fill(DS, "Art")
Return DS.Tables("Art").Copy
End Function
Sub doPaging()
pagedData.DataSource = getTheData().DefaultView
pagedData.AllowPaging = True
pagedData.PageSize = 2
Try
pagedData.CurrentPageIndex = Int32.Parse(Request.QueryString("Page")).ToString()
Catch ex As Exception
pagedData.CurrentPageIndex = 0
End Try
btnPrev.Visible = (Not pagedData.IsFirstPage)
btnNext.Visible = (Not pagedData.IsLastPage)
pageNumber.Text = (pagedData.CurrentPageIndex + 1) & " of " & pagedData.PageCount
ArtRepeater.DataSource = pagedData
ArtRepeater.DataBind()
End Sub
The ASP.NET is:
<asp:Repeater ID="ArtRepeater" runat="server">
<HeaderTemplate>
<h2>Items in Selected Category:</h2>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink runat="server" ID="HyperLink"
NavigateUrl='<%# Eval("ArtID", "ArtPiece.aspx?ArtID={0}") %>'>
<img src="<%# Eval("FileLocation") %>"
alt="<%# DataBinder.Eval(Container.DataItem, "Title") %>t"/> <br />
<%# DataBinder.Eval(Container.DataItem, "Title") %>
</asp:HyperLink>
</li>
</ItemTemplate>
</asp:Repeater>
If you need help with Connection Strings, this site is the ultimate resource!
http://www.connectionstrings.com/
Are you creating the connection string by hand? If so...don't do that! Use the Server Explorer to create your connection. Then highlight it and go to the Properties window, and you'll see the connection string it uses.
Also, using the Server Explorer will let you browse through your tables and even open them up to see your data. At least that'll tell you for certain whether your data is accessible.
Problem solved! Pretty much banging my head against the wall now considering how simple it was. It was the Page_Load, I changed it to the following:
Protected Sub Page_Load1(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
doPaging()
End Sub
And voila, it works!
Also, for the connection string, I ended up using:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\ArtDatabase.mdb
Which works great.
Thanks for your help and input guys!