Change select command of sqldatasource at runtime - c#

HTML
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="id" DataSourceID="SqlDataSource1">
<Columns>
<asp:BoundField DataField="id" HeaderText="id" />
<asp:BoundField DataField="name" HeaderText="name" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:database1ConnectionString %>"
SelectCommand="SELECT * from tblCourse"></asp:SqlDataSource>
Code
SqlDataSource1.SelectCommand =
"SELECT * from tblCourse where name='"+textbox1.text+"'";
SqlDataSource1.DataBind();
But Gridview does not change based on the new select command, even when I'm using DataBind()
How can we change grid view base on select command of sql data source?

This is happening because of GridView's viewstate.
When postback happens, gridview stores its data from ViewState. So, You can either turn off view state for GridView ( a good practice ?? ) OR you call GridView.DataBind() in addition to SqlDataSource.Databind();
METHOD 1: Calling GridView.DataBind();
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
{
string command = SqlDataSource1.SelectCommand; // added just for debug purpose
SqlDataSource1.SelectCommand = "SELECT * from tblCourse where
name='"+textbox1.text+"'";
SqlDataSource1.DataBind();
gridview1.DataBind();
}
}
METHOD 2: Turn off View State for GridView ( Is this a good Practice? ). When you set this false, there is NO need to call GridView.DataBind() in your page_Load as seen in above METHOD 1.
<asp:GridView runat="server" ID="gridview1" EnableViewState="false" ... />
Now the part comes that should must be taken care of::
Make sure the <asp:BoundField> or in general any fields declared and bound to GridView markup are also present in your new query else an error will be thrown saying something similar as below:
A field or property with the name 'ID' was not found on the selected data source

string strSql= "SELECT * from tblCourse where name='abc'";
ViewState["SQL"]=strSql;
SqlDataSource1.SelectCommand =strSql;
SqlDataSource1.DataBind();
Now in the Page_Load
if(IsPostback)
SqlDataSource1.SelectCommand=ViewState["SQL"].ToString();

You can either edit your BoundField's or change the property AutoGenerateColumns to true.

Set autogenerate to true and be sure to remove all the fields in the edit fields wizard. If you change the select command it causes the conflict.

Try adding the following :
SqlDataSource.select(DataSourceSelectArguments.Empty);
before the line SqlDataSource.DataBind();

Related

Gridview's (populated by SqlDataSource) Update is not updating, don't know how to trace

I'm still a newbie in ASP.NET, and right now, my Gridview is not "updating" when I hit "Update". Here is how I have my GridView w/ the SqlDataSource :
<asp:GridView ID="ProjectTable" runat="server" AutoGenerateColumns="False" AutoGenerateEditButton="True" DataSourceID="PopulateProjectTable" DataKeyNames="ProjectID">
<Columns>
<asp:BoundField DataField="ProjectID" HeaderText="Project ID" ReadOnly="True" SortExpression="ProjectID" />
<asp:BoundField DataField="ProjectDescription" HeaderText="Project Description" ReadOnly="True" SortExpression="ProjectDescription" />
<asp:BoundField DataField="ProjectNotes" HeaderText="Project Notes" SortExpression="ProjectNotes" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="PopulateProjectTable" runat="server" ConnectionString="<%$ ConnectionStrings:sandboxConnectionString %>" SelectCommand="SELECT * FROM [Projects]" UpdateCommand="UPDATE [Projects] SET ProjectNotes = #project_notes">
<UpdateParameters>
<asp:Parameter Name="project_notes" Type="String" />
</UpdateParameters>
</asp:SqlDataSource>
I have no code in the code behind. When I hit "Edit", the third column is suppose to be "editable". When I hit "Update", the page does a postback but what was entered in the third column does not persist and is instead lost. What is going on?
In addition, how would I trace this issue? This is so in the future, I can see what the SQL string is. Thank you.
EDIT: Turns out to be a typo that caused my issue. Problem solved!
Is the spelling correct on the ProjectNotes DataField? The problem you are describing sounds like the field is not bound properly.
I would run SQL profiler while hitting the update. To see what exactly was being sent back to the Database.
You should see your parameter as well. Set the filter to the DB your looking at if you have multiple and give it a try and realtime run the same test by hitting the update button again.
Please modify your update command from this
UpdateCommand="UPDATE [Projects] SET ProjectNotes = #project_notes"
to this
UpdateCommand="UPDATE [Projects] SET ProjectNotes = #project_notes" WHERE ProjectID=#ProjectID
Please add to your DataSource
OnUpdated="OnDSUpdatedHandler">
and add the following method
<script runat="server">
private void OnDSUpdatedHandler(Object source, SqlDataSourceStatusEventArgs e) {
var dbg = e;
}
</script>
Set breakpoint on line
var dbg = e;
and examine what is being in that variable. The answer should be there

Change the name of column in Gridview on runtime when sorting of gridview is enabled

I want to change the name of one of the column of gridview on runtime.The Gridview has also sorting enabled in it.
the gridview looks like:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true" OnRowCreated="myGrid_Rowcreate"
ShowFooter="false"
AllowSorting="true"
OnSorting="GridView1_Sorting"
EnableViewState="false"
ShowHeaderWhenEmpty="True"
AllowPaging="false">
<AlternatingRowStyle CssClass="altrowstyle" />
<HeaderStyle CssClass="headerstyle" />
<RowStyle CssClass="rowstyle" />
<RowStyle Wrap="false" />
<HeaderStyle Wrap="false" />
</asp:GridView>
and my onRowCreate function looks like:
protected void myGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
GridViewRow gvr = e.Row;
if (gvr.RowType == DataControlRowType.Header)
{
gvr.Cells[1].Text = "test1";
}
}
the column name does change to test1 but the sorting feature goes off.what should I do that will change the coulmn name as well as the sorting feature also stays?there is no problem in my sorting.Only when I write the above code,the sorting option for that column goes off.
Please help!
thank you.
The problem is because Sorting sets a LinkButton control in the GridView columns name, and setting the name in the way you do it, disable that control. So, you must set the name of the column with a code like:
((LinkButton)e.Row.Cells[1].Controls[0]).Text = "Test1";
I'm guessing you're trying to use AutoGenerateColumns?
If this is the case why can't you change the column name in the datasource (using "AS" if the datasource is SQL)?
Otherwise, your altering the cell text is short-circuiting the ASP.NET functionality which generates the sorting javascript postback.
Alternatively you would do this if you don't use AutoGenerateColumns:
myGrid.Columns[1].HeaderText = "test1";
I think your problem comes from the postback sent when you order your grid. You don't want to rebind your grid after ordering it.
In your pageLoad you should add :
If(!PostBack)
// the code to bind data to your grid
This way you prevent the grid to be reloaded and the information you set in myGrid_RowDataBound for the name your column should stay the same...

ASP.NET 2.0 with conditional radio button in a GridView

I'm looking to have a GridView displaying "Events" from a database, and then in the last column I want to do another database lookup (for each row) to see if that event is full or not.
If it's not full, display a radio button. If it is full display text "Full".
I think this is best done with OnRowDataBound event but could use a little help.
I can see how to change an asp label text but not display a radio button.
register.aspx:
<asp:GridView ID="GridView2" runat="server" DataSourceID="SqlDataSource2" AutoGenerateColumns=false CellPadding="5" HeaderStyle-BackColor="DarkGray" Width="450px" OnRowDataBound="GridView2_OnRowDataBound">
<Columns>
<asp:BoundField DataField="sessionDate" HeaderText="Date" DataFormatString="{0:D}" />
<asp:BoundField DataField="sessionTime" HeaderText="Time" />
<asp:BoundField DataField="site" HeaderText="Site" />
<asp:BoundField DataField="room" HeaderText="Room" DataFormatString="{0:D}" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<input type="radio" name="rdoSessionID" value='<%# Eval("ses_ID") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#99CCFF" />
</asp:GridView>
<br />
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:sqlConnection2 %>"
SelectCommand="SELECT * FROM dbo.sessions WHERE site LIKE #ses_site AND sessionDate = #ses_date ORDER BY sessionDate">
<SelectParameters>
<asp:SessionParameter name="ses_site" SessionField="ses_site" Type="String" />
<asp:SessionParameter name="ses_date" SessionField="ses_date" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
There are a few ways you can do this.
You can do this on the OnRowDataBound , If the Item you're dealing with is a DataItem, grab the value you need from the current row, and do a quick DB Lookup
When you get your resultset back from the database, do another lookup on each event. This way when your data leaves your data layer / methods you already have everything you need.
Modify your SQL query to return this information with the list of events. You already know the Events, you could just have a sub query to query to see if it's full or not (or the # of people registered, and the Max # allowed so you can show that). This way you only have to do 1 hit against the database and it will save you a bunch of processing. (My favorite)
You would still need to overload the OnRowDataBound event for all 3 of those solutions. You'd hide the radio button if it was full, and ensure it was visible if the event was not full. The difference is where do you get your data.
Do you want to do:
1 Good hit (list of events)
X amounts of small hits for each event
or
1 Good hit for list of events + if each event is full or not.
If you want to entertain #3, post your SQL Query and we can go from there.
Quick example of the OnRowDataBound event.
protected void MyGridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox cbox = (CheckBox)e.Row.FindControl("chkBox");
// Do some funky logic
cbox.Visible = Event.HasRoom; //Boolean Propery
// Or
cbox.Visible = Convert.ToBoolean(DataBinder.Eval(e.Row.DataItem, "HasRoom").ToString());
}
}
Update 1:
For your GridView, You can use
<ItemTemplate>
<asp:CheckBox runat="server" ID="Checkbox1" ToolTip=" Sign up For event " text="Event stuff" />
</ItemTemplate>
If you want to use a template, don't use a regular control, use a control.
For the query you could do the following. I'm not 100% sure on your table structure so I did it the way I normally would:
Table: Session (sess_id(PK), SessionDate, SessionTime, Site, Room)
Table: Registrants (RegistrantID (PK), sess_id (FK to Session), UserID (FK to users that are registered)
SELECT SessionDate, SessionTime, Site, Room, ses_ID,
(SELECT Count(ses_ID) FROM Registrants R WHERE R.Ses_ID= S.ses_Id) as [Registrants]
FROM dbo.Sessions s
Use the OnRowDataBound event, like this:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
RadioButton radio = e.Row.FindControl("RadioButton1") as RadioButton;
if (radio != null)
{
radio.Visible = SomeCheckThatReturnsBoolean((int)GridView1.DataKeys[e.Row.RowIndex]["SomeID"]);
}
}
If possible though, you should return the data with the GridView results, and store the value in a data key, so you can do something like this:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
RadioButton radio = e.Row.FindControl("RadioButton1") as RadioButton;
if (radio != null)
{
radio.Visible = (bool)GridView1.DataKeys[e.Row.RowIndex]["SomeBooleanValue"];
}
}
EDIT: Based on your comment to #Ryan, I think you should be able to include that flag in your query. I don't know your database at all, but you can try using a derived table or subquery to get the registrant session counts. Here's a rough example to work off of:
SELECT ID,
ISNULL(Registrants.RegistrantCount, 0) RegistrantCount
...
FROM Table1 t1
LEFT OUTER JOIN (
SELECT ForeignKeyID,
COUNT(RegistrantID) RegistrantCount
FROM Registrants
GROUP BY ForeignKeyID
) Registrants
ON Registrants.ForeignKeyID = t1.ID

ASP. NET C# GridView Paging

Hi good day to all. I have this web application for a certain company. In this web application there is a part that uses GridView to display records from the database and the way it is being displayed it is hard coded. I'll display my codes bellow.
string SQLCommand = "SELECT LastName +', ' +FirstName + ' '+MiddleInitial AS 'Name', UserName + ' 'As 'User Name', StreetAddress FROM CustomersMaster Where LastName Like '%"+ SearchText.Text.Trim() + "%'";
SqlCommand com = new SqlCommand(SQLCommand, con);
SqlDataAdapter adp = new SqlDataAdapter(com);
DataTable tbl = new DataTable();
adp.Fill(tbl);
AdminViewBuyersGV.DataSource = tbl;
AdminViewBuyersGV.DataBind();
My problem is I want to use the "Paging" property of the GridView but when I activated the "Paging" property and then when I run it there's an error that says that "The data source does not support server-side data paging". I just want to know how to use paging when I already hard-coded it.
Is there a way on how to solve my problem. Thank You in Advance and God Bless! :)
Make sure you are acting on data...
if (tbl.Rows.Count > 0)
{
AdminViewBuyersGV.DataSource = tbl;
AdminViewBuyersGV.DataBind();
}
else
{
// no records
}
did you write code for the AdminViewBuyersGV_PageIndexChanging routine?
Unless you have a good reason for binding your datasource in code, you might want to look at using a SqlDataSource control in the .aspx page. You can give it a parameter (which is safer than building a sql string the way you are) and it should support paging out of the box...
Ok, so full example using SqlDataSource (as Kendrick mentioned):
First you need to collect the parameters from your query, which it looks like you are already doing in a textbox somewhere. Something like this:
<asp:Label ID="lblLastName" runat="server" AssociatedControlID="tbLastName" Text="Last Name" ClientIDMode="Static" />
<asp:TextBox ID="tbLastName" runat="server" ClientIDMode="Static" />
<asp:Button ID="btnSearch" runat="server" ClientIDMode="Static" Text="Search" />
Now we need to take your Raw Inline SQL out of the code behind and move it into a SqlDataSource. We also want to get rid of the potential SQL Injection you have in your query by using a parameterized query instead :) In order to do that we need to hook up our TextBox to the parameter, but luckily DataSource controls allow us to do this without any code by using SelectParameters.
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ContactManagerConnectionString %>"
SelectCommand="SELECT LastName + ', ' + FirstName + ' ' + MiddleInitial AS 'Name', UserName AS 'User Name', StreetAddress FROM CustomersMaster WHERE (LastName LIKE '%' + #SearchText + '%')">
<SelectParameters>
<asp:ControlParameter ControlID="tbLastName" ConvertEmptyStringToNull="true"
Name="SearchText" PropertyName="Text" DbType="String" />
</SelectParameters>
</asp:SqlDataSource>
Once those two pieces are in place it is just a matter of setting up your grid the way you want, and setting the AllowPaging property to true.
<asp:GridView runat="server" AllowPaging="True" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" ReadOnly="True"
SortExpression="Name" />
<asp:BoundField DataField="User Name" HeaderText="User Name"
SortExpression="User Name" />
<asp:BoundField DataField="StreetAddress" HeaderText="StreetAddress"
SortExpression="StreetAddress" />
</Columns>
</asp:GridView>
VOILA!
Codeless paging*
* It is worth noting that this is pretty poor in terms of optimization as all the paging work is done on the Web Server. To really make this efficient you would want to employ some paging at the database level. Otherwise you will bring back every record every single time.
It says it doesn't like the data you are binding. So try to tidy the data you are binding:
AdminViewBuyersGV.DataSource = tbl.ToList();

Gridview Column Removing

I have a web application that I am working on(ASP.NET 2.0 C#). In it I have a GridView whose data source is an Oracle database. I get the data into the gridview in my codebehind, and don't set the datasource directly.
I wanted to create a hyperlink field (NAME) that takes me to a details page about a specific record. What ends up happening is that it creates the Hyperlink field as well as the regular field that it gets from the datasource, which I don't want. If I remove the field from my SELECT statement, it gives an error saying something like: "NAME" not found in datasource.
How can I eliminate the regular field, and get a hyperlink field instead? I have tried Gridview.Columns.Remove(columnlocation), but that won't work coz the columns don't exist there originally.
Please Help
Thank you.
Instead of removing columns, disable AutoGenerateColumns property of the gridview and set your hyperlink column manually like that :
<asp:gridview id="GridView1"
autogeneratecolumns="false"
runat="server">
<asp:HyperLinkField DataNavigateUrlFields="UserID"
DataNavigateUrlFormatString="UserDetails.aspx?id={0}"
DataTextField="UserName" />
</asp:gridview>
Sounds like you have AutoGenerateColumns property set to TRUE on your grid. This means that a column is generated for EVERY column you return from your query.
If you want to have some custom columns, you should set AutoGenerateColumns="false" and add all the columns to the GirdView as asp:BoundField and your Hyperlink column as asp:TemplateField
Let me know if I'm off the mark with this
here's some code:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Name" />
<asp:BoundField DataField="Whatever" />
<asp:TemplateField>
<ItemTemplate>
<a href='<%# Eval("UserId", "URL_TO_USER?userId={0}") %>'>Details</a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

Categories