gridview filtering via joined tables - asp.net

I'm trying to display data which comes from a join on two tables (or more) in a gridview
I want to be able to filter the result set via user given input (text boxes on page)
I have tried the standard tutorials but cannot find something which goes beyond displaying one table result sets in the gridview. If I go through the configure gridview and configure datasource wizard for any datasource (sqlDatasource, object, entitydatasource), when I use multiple tables I cannot use the 'where' parameters in the wizard, and therefore need to have the selecting code in the code-behind, but i'm unsure where exactly to put this.
e.g. if I have
Protected Sub button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles button1.Click
sqldatasource1.selectcommand = "select * from yourtable where modelfamily
like '%" & textbox1.text & "%' or description like '%" &
textbox1.text & "%'"
sqldatasource1.databind()
End Sub
then this code will help with a search button for part 2 of my question, e.g. if button1 is a search button then I can incorporate the text box values in the query and bind,
but where would I place the intiial data binding code, in page_load? And where shall I place the other other code? Please could you provide me a link to a solution, or better help me here please.
I want to be able to:
use entity data source to do this (how can I do this multiple join in entity framework, or other source if much easier)
I want to display all the results intially (coming from two tables) with paging and sorting enabled
if text box has a value and search button clicked, then subset of the data based on the value is shown, and is also page-able/sort-able within itself.
Please can you show me examples of where would the code sit, which events and what will it look like?

Have a look at this Inner Join statement and gridview

Related

DropDownList populates based on First DropDown Metro Station Colors

I know how to do this pragmatically with using a OnSelectedIndexChange and a event on the first dropdown. I'm trying to figure out the best way to do this architecturally since in my case I'm dealing with Metro stations where a particular station will have more than one color.
e.g.
First Dropdown List with Color (i.e. Red, Green, Purple)
2nd Dropdown List with Stations
"1st Street - Red and Green"
"Bloom Ave - Green"
"Titan Station - Red Purple"
So if the user selects Red on the FIRST dropdown, the 2nd dropdown should populate with "1st Street" as well as Titan Station". If the user selects Green it should just display "Bloom Ave".
There are many stations with color overlap (more than one color).
The proper way in my mind to do this is create a table with station names and a column for each color with the datatype BIT. If a station has more than one color, those columns would be set to 1 or True. I would have a stored procedure that would fire, the procedure would perform a selection based on color and then show all applicable stations which would bind to the 2nd dropdown.
Is there another way to do this entirely pragmatically, by just the dropdowns itself. Example, you write this logic in the DropDownList control and it knows what's associated with what?
Well, you certainly don't want to start or introduce into your project some kind of bit row wise processing for what amounts to a rather simple and "class" relational model in database land for your solution.
I mean, if you have a customer, and they are to have many invoices, then we don't introduce some bit-wise processing here. (because sql server don't work that way).
So, if you have some customers, then if you need "many" invoices, then you create a invoice table.
If you have some Stations, and they can have 1 or 10 different colors, then you make a table called MyStationColors. This is how all data base operations work.
In fact, the only real question is do you want to store the color (as text name), or do we store the PK id of the color (from our table of colors).
I tend be it a customer, a color, or whatever? I store the PK id, and we are free to display some nice user friendly color description as we please.
so, we need:
Colors - a simple table of all the colors we are going to use
Station - a simple table of all the stations
MyStationColors - a table that lists out all the colors for a given station.
So, once we have the above, then this all becomes a rather simple SQL and database example.
So, we will have 3 tables. Say like this:
Now, I have not introduced any relationships between the color table. After all, it really is just a pick list, or our main list of colors. but, we can add a relationship to that table if we want (it would prevent us from deleting colors are are currently in use by a given station. But, lets keep this simple.
So, our first combo box will be driven (filled out) by a simple combo box, and we feed it the colors table.
And as noted, we went with "id", but a combo box is able to have TWO columns, usually the PK (for code behind), and 2nd color for display to your users.
So, drop in a combo box, say like this:
<asp:DropDownList ID="DropDownList1"
runat="server"
DataValueField="ID"
DataTextField="Color" Width="141px"
AutoPostBack="true" >
</asp:DropDownList>
(don't forget the auto post back in above!!!)
Note the "two" columns for the drop down (Value is hidden, Text is display).
And code to fill combo is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadCombo()
End If
End Sub
Sub LoadCombo()
Dim cmdSQL As New SqlCommand("SELECT ID, Color FROM Colors ORDER BY Color")
DropDownList1.DataSource = MyrstP(cmdSQL)
DropDownList1.DataBind()
DropDownList1.Items.Insert(0, (New ListItem("Select Color", "0")))
End Sub
And now we see/get this:
And dropping the box, we see this:
So, now all we have to do is wire up the selected index change event.
but, before we do that, and I am VERY lazy, lets use sql studio, and create a view (a query) that will display the stations and their colors. We use that for the "display" of the results.
So, new view in sql server, and we get to do this via drag/drop and GUI (after all, who's going to write that sql by hand, right???).
So, we have this:
And when we run above, we get this:
As we can see, some stations have more then one color, so they show up more then one time. But, we let the query builder in SSMS build that sql above for us - all drag and drop so far.
Ok, save that view (Vstations).
Now, we need to display the results of our choice. So, lets drop in a grid view like this:
<asp:DropDownList ID="DropDownList1"
runat="server"
DataValueField="ID"
DataTextField="Color" Width="141px" >
</asp:DropDownList>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
And now in property sheet for dropdown, we add the selected index event (double click here:)
And now the code for selecting the combo is this:
Protected Sub DropDownList1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles DropDownList1.SelectedIndexChanged
Dim strSQL As String =
"SELECT * FROM StationsV WHERE COLOR_ID = #COLOR"
Dim cmdSQL = New SqlCommand(strSQL)
cmdSQL.Parameters.Add("#COLOR", SqlDbType.Int).Value = DropDownList1.SelectedItem.Value
GridView1.DataSource = MyrstP(cmdSQL)
GridView1.DataBind()
End Sub
So, now when we select a color, all the stations with a given color will show like this:
Now, of course we should clean up the grid, remove the "ID" and also remove color_id from that grid. But that's just nuts and bolts.
and of course a extra bonus would be to say show all the colors for a given station in above. And we can do that. But, as you can see, these problems are best approached by using a correct data model to reflect the real world case of a station having many colors. And we don't thus mess or introduce some kind of complex bit wise processing. We most certainly did have to introduce a extra table (to keep track of colors for a given station), but other then this bit of extra work, once done, then we are free to add 1 or 5 colors to a station, and we don't have to change the design, or even say assume or add some bit color for a given color.
Be it customers and invoices, or a station with some colors - the relational data model approach tends to make such problems rather easy.
Last but not least, I do get tired of typing connection and loading of a data table over and over, so I also used and had this handy routine MyRstP to return a datatable.
Public Function MyrstP(sqlCmd As SqlCommand) As DataTable
Dim rstData As New DataTable
Using sqlCmd
sqlCmd.Connection = New SqlConnection(My.Settings.TEST5)
sqlCmd.Connection.Open()
rstData.Load(sqlCmd.ExecuteReader)
End Using
Return rstData
End Function

PagedDataSource not working with previous/next pages

I'm having a hard time with this scenario and hoping someone can help me clarify where I'm missing a step/logic. I tried searching online but I couldn't find an example that addressed this issue.
We are setting up a search page that when first loads shows a bunch of options (e.g., textboxes, checkboxes, etc). The user will fill out the form and submit the form back to itself. Once posted back, the page will build and run a SQL query (e.g., SELECT ID FROM Customers WHERE Company = 'Acme' AND AmtDue = 3) against the database with the user's options and then the results will show up. This part works ok.
The part that breaks down is when I am trying to add pagination. The result set is a DataTable bound to a Repeater. I am using a PagedDataSource to add pagination. Pagination works great for the first page but for subsequent pages, it does not work. Basically, instead of returning the next page of the result requested (e.g., SELECT ID FROM Customers WHERE Company = 'Acme' AND AmtDue = 3), the results returned is the SQL query before appending the user's search options (e.g., SELECT ID FROM Customers).
I think my basic problem is that I'm not sure how to distinguish a normal Page.IsPostBack and paginating through results. The reason why this is causing problems is because I don't want to be regathering form data, rebuilding query, and requerying the DB.
The examples that I found online involved pagination of a DataTable that is rebuilt every time the page loads (e.g., Not Page.IsPostBack).
Here is a rough outline of our code:
Public dtCustomers As DataTable = New DataTable()
Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load
' When the page first loads, show the search form with search options.
If Not Page.IsPostBack Then
ShowSearchForm()
' Once the form is submitted, show the search results.
Else
' ----------------------------------------
' This is the part that I'm having trouble with. How do I skip the following two steps (GatherFormData() and BuildDT()) when the user requests a subsequent page?
GatherFormData()
dtCustomers = BuildDT()
' ----------------------------------------
BindData()
End If
End Sub
Sub BindData()
Dim objPDS As PagedDataSource = New PagedDataSource()
objPDS.DataSource = dtCustomers.DefaultView
objPDS.AllowPaging = True
objPDS.PageSize = intNumPerPage
objPDS.CurrentPageIndex = Me.ViewState("_CurrentPage")
rptSearchResults.DataSource = objPDS
End Sub
' Subroutine called when the previous page button is pressed.
Sub GoToPrevPage()
' Set viewstate variable to the previous page.
Me.ViewState("_CurrentPage") -= 1
BindData()
End Sub
' Subroutine called when the next page button is pressed.
Sub GoToNextPage()
' Set viewstate variable to the next page.
Me.ViewState("_CurrentPage") += 1
BindData()
End Sub
Note: I understand that the DataTable will have to be put into cache or a session variable, but haven't decided the best method.
Please excuse the code outline but the actual code is massive so the simplification is to make it easier to get to the heart of the issue.
Let me know if any of that was unclear. Thanks in advance!
I am assuming that you are going to store your data in session/cache (I would prefer the later but there can be use case for storing it in session) - you can store the key in the view-state and presence of key could be use to determine if post-back is for pagination or not. For example,
if (ViewState["dataKey"] == null)
{
// first form submittal, do the search
GatherFormData();
dtCustomers = BuildDT();
// store it in cache
ViewState["dataKey"] = Guid.NewGuid().ToString(); // create a key
Cache.[ViewState["dataKey"].ToString()] = dtCustomers; // TODO use Add method to control expiration etc
}
Its important that you clear the view-state when the search is reset (or similar condition)
Lastly, it is also possible to do the paging from database/data-store (for example, using ranking functions in SQL Server) so that you need not have to store the search results into the session/cache but rather do a database trip at each post-back. Such approach is useful when the complete result set size can be huge.

PageIndexChanging Without Binding

I have datagridview linked with dataSource, this data source get data from table has 9 Million record and I'm searching in this table by name, after Binding data when need to change PageIndex this requires to research in 9 million records by this code:
Any method to change PageIndex without binding it again?
Protected Sub GVCenteralSearch_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GVCenteralSearch.PageIndexChanging
GVCenteralSearch.PageIndex = e.NewPageIndex
GVCenteralSearch.DataSource = CentralSearch_DS
GVCenteralSearch.DataBind()
End Sub
Notes : This Is Based on WebApp (ASP.net)
Not that I know of. You do have a few options though, you can cache the data so you don't have to get it from the database again. You could also look into javascript alternative to paging the data (jQuery DataTable plugin). Alternatively you can re-write the query to only grab the records you need. This would still take the round trip to get the data displayed, but it won't be as significant.

How do i get row keys / cell values & call a method when a row is selected in the standard .net 2.0 Gridview

I have standard .net 2.0 gridview control from which i want to get row keys or cell values from the grid when a row is selected.
I also need to call a method each time a row is selected.
Does anybody know How i can do this using ASP.net & VB?
I assume you mean selection by the Select command. That fires a SelectedIndexChanged event. and from there on you have the SelectedDataKey.Value (or .Values) for the Key.
Protected Sub GridView1_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles GridView1.SelectedIndexChanged
Dim key As Object = GridView1.SelectedDataKey.Value
End Sub
Add a button or link button to your gridView.
For the command name put in "Select"
In the designer window, double click your gridView and your selected index changed method will be automatically generated.
I prefer using third-party grid like the Telerik one which allows server and client selection as well as postback on click to process some logic.
Dick

Insert record with EmptyDataTemplate in asp:ListView

I have an EmptyDataTemplate in my asp:ListView which I want to use to insert a new record.
I have Inserting working in the InsertItemTemplate... I thought I could copy the InsertItemTemplate into the EmptyDataTemplate, on clicking Insert this gives the error
Insert can only be called on an insert item. Ensure only the InsertTemplate has a button with CommandName=Insert.
How can I use the EmptyDataTemplate to Insert a row? Do I need to use the OnClick of the button to access the values within the EmptyDataTemplate and do an Insert by myself?
I'm using LinqDataSource
You might have figured it by now
but if you set the InsertItemPosition to anything other than None the EmptyData Template will not be rendered i.e it will always show the insert template
you can read more here
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listview.emptydatatemplate.aspx
No way if want to insert data in empty data template.
It is possible to do an insert from the EmptyDataTemplate by handcrafting the insert. I am using a listview to display a static number of rows based on a unique filtered item. I am basically listing all the static attributes of an object. In the case where a new object is filtered on that does not have any attributes associated with it, i use the EmptyDataTemplate of the listview to display a HTMLTable that contains asp.net controls to capture data. I have a command button within the table that i evaluate using the ListView_ItemCommand. If the CommandName matches that of the "Insert" button within the EmptyDataItem, I use the ListView.Controls(0).FindControl method to locate my table. I then loop through my table and do inserts on the data found within each row. I included the how to find a control within the htmltable. In my code I am actually grabbing a bunch of controls then crafting the sql and using a SQLConnection to perform the insert.
Protected Sub ListView_ItemCommand(sender As Object, e As System.Web.UI.WebControls.ListViewCommandEventArgs) Handles ListView.ItemCommand
Select Case e.CommandName
Case "Submit"
Dim edt As HtmlTable = ListView.Controls(0).FindControl("myhtmltable")
Dim ddl As DropDownList = CType(edt.FindControl("mydropdownlist"), DropDownList)
'Perform Insert
Case "Some other commandname"
End Select
End Sub
You will need to still do error checking and databind() and refresh your listview.
Is this the best way. Maybe not... But it is possible.
~Ian

Resources