Dynamic Columns and Data Sources with .NET Grid View - asp.net

I am working on a multi-purpose page and rather than adding multiple grids to the same page we wanted to use a single GridView to the page, and on Page_Init add the needed columns, and set the respective DataSourceID.
So to do this, we have something like the following in the aspx, the codebehind in the Page_Init is very simple adding a few columns then setting the DataSourceID property of the GridView.
ASPX:
<asp:GridView ID="gvDisplay" runat="server" AutoGenerateColumns="false" CellPadding="5"
width="100%" AllowPaging="true" PageSize="200" DataSourceID="wuProcessLogDataSource">
<RowStyle CssClass="RowStyle" />
<AlternatingRowStyle CssClass="AlternatingRowStyle" />
<HeaderStyle CssClass="HeaderStyle" />
</asp:GridView>
<asp:ObjectDataSource id="wuProcessLogDataSource" runat="server" EnablePaging="True"
SelectMethod="GetWUProcessLog" TypeName="Project.Objects.WUProcessLogDal"
SelectCountMethod="GetWUProcessLogTotalRecords">
<SelectParameters>
<asp:QueryStringParameter QueryStringField="w" DefaultValue="0" Name="workunitId" />
</SelectParameters>
</asp:ObjectDataSource>
The object data source is there and working as the first page load triggers without any issues at all. However, as soon as you click on a page button, the grid disappears from the page? Any ideas?
I would just use a DataGrid but it doesn't have the desired dynamic display abilities for the HyperLinkColumn.

It sounds like you're doing something like
If (!Page.IsPostBack)
{
//create + add columns - set datasource etc
}
If that's the case - then you need to remove the check and always generate the columns (I'd also suggest disabling viewstate for the datagrid)

try the page load event instead of page init

Related

ASP.Net GridView styling - invisible cell lining

I`m using a Gridview in an ASP.Net web app.
Since it has custom styling and templates, I couldn't figure how to style it the way I want. I want all the lines of the final HtmlTable to be invisible - just purely the cellcontent and margins between them, without a visible table. How can I do such a thing?
The gridView itself:
<asp:GridView
ID="Items" runat="server">
</asp:GridView>
<asp:GridView
ID="Items" runat="server" GridLines="None"
CellSpacing="Set a Value" CellPadding="Set a Value">
</asp:GridView>

Is it possible to use a control in a different content tag as a parameter?

I currently have two Web Controls, one being a CheckBoxList, and the other a GridView. The GridView's data configuration has a parameter in it's query which is linked to the selected values from the CheckBoxList. However, when the two controls are in separate content tags like so:
<asp:Content ID="ListPanel" runat="server" ContentPlaceHolderID="LeftContent">
<h3>Pick Info Here</h3>
<asp:CheckBoxList ID="cbList1" runat="server"
DataSourceID="TestDataSource"
DataTextField="St" DataValueField="St" RepeatColumns="2">
</asp:CheckBoxList>
</asp:Content>
<asp:Content ID="ResultsPanel" runat="server" ContentPlaceHolderID="RightContent">
<asp:GridView ID="gView1" runat="server"
AllowPaging="True" AllowSorting="True"
AutoGenerateColumns="False" DataSourceID="TestDS1">
<Columns>
...
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="TestDS1" runat="server"
...
SelectCommand="SELECT ST FROM [Table] where ST = ?">
<SelectParameters>
<asp:ControlParameter ControlID="cbList1" Name="?"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
</asp:Content>
It works fine when I put both controls in the same <asp:Content> tag, but things call apart with an error of System.InvalidOperationException: Could not find control 'cbList1' in ControlParameter '?'. Is there a way to keep the controls separate, or do they have to be inside the same content tag?
Seems a little krufty but you could put a HiddenControl in the ResultPanel and then set it's value to that of cbList1.SelectedValue on page load.
I know you can access controls regardless of the Content they are in, from code behind but apparently you can't from within the Content itself on the aspx side.
Apparently this can be done by prefixing the ContentPlaceHolderID to the ControlID of the parameter entry. In my case, the code would be:
SelectParameters>
<asp:ControlParameter ControlID="LeftContent:cbList1" Name="?"
PropertyName="SelectedValue" />
</SelectParameters>
since the Control the parameter reads from is in the LeftContent tag.
Some years later... I had the same problem with a gridview and a control parameter. In the source-code of the rendered page, you can find the exact "path" to the element. In my case it was not only gv1$txtEmployeeName, but gv1$ctl02$txtEmplyeeName.
I guess, ctl02 means EditItemTemplate, because including ctl02$ solved my problem.

DotNetNuke: ObjectDataSource for GridView not being found

As a follow-up to a previous question about GridView and DotNetNuke, I'm having a little more trouble getting things to act correctly. Right now I have a simple GridView in my ascx file and I bind the data to the GridView in my .cs file like so:
DiscoveryController objDiscoverys = new DiscoveryController();
List<DiscoveryInfo> lstDiscoveries = objDiscoverys.GetDiscoverys(ModuleId);
grdDiscoverys.DataSource = lstDiscoveries;
grdDiscoverys.DataBind();
This works. However, I have seen an alternate method in a tutorial which instead defines an <asp:ObjectDataSource> in the controller, and this seems to allow the Designer to do more intelligent things, such as add functioning Delete buttons through a checkbox. Later on in the tutorial, I see inline editing being done as well, which is functionality I desire.
So I decided to give it a shot. To wit:
<asp:ObjectDataSource ID="objDataSource" runat="server" TypeName="MyCompany.Modules.Discovery.DiscoveryController" />
As my dll file in the bin folder is named MyCompany.Modules.Discovery (which matches the assembly name and default namespace I have set up in my C# project), this makes perfect sense. As the tutorial says, I then used the Designer to attempt to bind the Data Source to the GridView.
However, I get an error message that it can't be loaded. The namespace names and class name match up, and I can clearly bind it from the codebehind, so what gives?
EDIT: A follow up. After some experimentation, I have discovered that while the Designer cannot see my module, the .ascx template itself can. Putting this in my .ascx file seems to work...for the most part:
<asp:ObjectDataSource ID="objDataSource" runat="server" TypeName="MyCompany.Modules.Discovery.DiscoveryController" SelectMethod="GetDiscoverys" UpdateMethod="UpdateDiscovery" DeleteMethod="DeleteDiscovery">
<SelectParameters>
<asp:QueryStringParameter Name="ModuleId" QueryStringField="mid" />
</SelectParameters>
<UpdateParameters>
<asp:QueryStringParameter Name="ModuleId" QueryStringField="mid" />
</UpdateParameters>
<DeleteParameters>
<asp:QueryStringParameter Name="ModuleId" QueryStringField="mid" />
</DeleteParameters>
</asp:ObjectDataSource>
<asp:GridView ID="grdDiscoverys" runat="server" DataSourceID="objDataSource" EnableModelValidation="True" AutoGenerateColumns="false" AutoGenerateEditButton="true" AutoGenerateDeleteButton="true" DataKeyNames="ItemId">
<Columns>
<asp:BoundField DataField="ItemId" HeaderText="#" ReadOnly="true" />
<asp:BoundField DataField="Title" HeaderText="Title" />
<asp:BoundField DataField="Image" HeaderText="Image URL" />
<asp:BoundField DataField="Link" HeaderText="Link" />
</Columns>
</asp:GridView>
Fantastic...it looks like I've mirrored most of the functionality of what the Designer would have added...except for one teensy little thing. The automatic update doesn't update.
More specifically, I get this message when I try to update a field:
ObjectDataSource 'objDataSource' could not find a non-generic method 'UpdateDiscovery' that has parameters: ModuleId, Title, Image, Link, ItemId.
Of course it doesn't work! The method signature goes like this:
public void UpdateDiscovery(DiscoveryInfo objDiscovery)
At this point, I'm so close to getting something working that I can taste it, and DAL-be-damned I'm about to change the function so it takes those five exact params instead of a data object. However, the tutorial that I referenced above seemed to somehow convince the automatic update to pass a data object, so I'm kind of curious to know how it got away with it.
Change your object data source declaration to match your update method:
public void UpdateDiscovery(DiscoveryInfo objDiscovery)
Use single parameter in update parameter declaration:<UpdateParameters>
<asp:Parameter Name="objDiscovery" />
</UpdateParameters>
use object data source's updating event to create an object from the existing control set and assign it to parameter's default value.
Good luck

ASP.NET how best to add a delete confirmation on a gridview with EntityDataSource

I have a .NET4 web application using the Entity Framework
In one of my pages I have a gridview bound to an entity data source. Within the Gridview definition I have
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
and the EntityDataSource is defined
<asp:EntityDataSource ID="eds_timesheets" runat="server" ConnectionString="name=TIME_ENTRY_DB"
DefaultContainerName="TIME_ENTRY_DB" EnableDelete="True" EnableFlattening="False"
EnableUpdate="True" EntitySetName="TIMESHEETs" Include="USER, ACTIVITY, PROJECT"
EntityTypeFilter="TIMESHEET">
</asp:EntityDataSource>
Everything works as expected, however I now want to put a confirmation of delete in place in case of accidental pressing.
I have tried placing code on the row command of the gridview wwhich would register a javascript alert window however it appears that at this point the EntityDataSource has already carried out its delete.
There is no OnClientClick for a gridview command field to place a small javascript snippet.
Has anyone encoutnered and subsequently solved this issue? Is it easier to have a link button and handle the delete of the Entity data source myself?
Use a TemplateField, and then put a Button in it with the CommandName="Delete". Then you can use the OnClientClick property to call your javascript confirmation.
Something like the following (can use Button, ImageButton, or LinkButton):
<asp:TemplateField>
<ItemTemplate>
<asp:Button id="DeleteButton" runat="server" text="Delete"
CommandName="Delete" OnClientClick="return confirm('Are you sure?');" ></asp:Button>
</ItemTemplate>
</asp:TemplateField>
Of course, you would not want to show the delete button in the CommandField.

Adding Link Column to ASP.NET GridView

I want to output a list of news headlines that are clickable. So far I can get it to print out a list of headlines because I dragged and dropped the NewsHeadline table in designer view in VS 2010. How do you think I should the make the list elements clickable? I looked for a URL attribute but I did not see it. Do I need to wrap in a < a href ?
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1"
EmptyDataText="There are no data records to display.">
<Columns>
<asp:BoundField DataField="NewsHeadline" HeaderText="NewsHeadline"
SortExpression="NewsHeadline" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString1 %>"
ProviderName="<%$ ConnectionStrings:ConnectionString1.ProviderName %>"
SelectCommand="SELECT [NewsHeadline] FROM [NewsTable]"></asp:SqlDataSource>
</form>
You need to change the column type from a BoundColumn to a Hyperlink column.
<asp:hyperlinkfield headertext="NewsHeadline"
datatextfield="NewsHeadline"
datanavigateurlfield="NewsURL"
datanavigateurlformatstring="http://{0}" />
In addition to making this change, you'll need to make sure that you are selecting the URL or something you can use to create the link to the news article. In the example above, I'm assuming the URL is something you can grab from your SQL source. If it is an ID, simply type out the rest of the url like this... "~/MyNewsPage.aspx?NewsID={0}"...
Use hyperlinkfield instead :
<asp:hyperlinkfield datatextfield="NewsHeadline"
datanavigateurlfields="NewsID"
datanavigateurlformatstring="~\newsdetails.aspx?Id={0}" />
You need to use a hyperlink field instead of a BoundField, like so:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1"
EmptyDataText="There are no data records to display.">
<Columns>
<asp:HyperLinkField HeaderText="NewsHeadline" SortExpression="NewsHeadline" DataTextField="NewsHeadline" NavigateUrl="..." />
</Columns>
Something like this will work fantastic as a solution in Visual Studio 2010.
Create a GridView in the Designer tab of your webpage in VS.
Hover your mouse over the GridView and click the arrow that appears in the top right.
Go to "Choose Data Source" and select "new data source..."
Create the connection string to your database and choose the NewsHeadline table.
Write the query SELECT News_Id, NewsHeadline FROM NewsHeadline
Finish the setup. Now some code should be generated in the Source tab. This will also create an SqlDataSource which is now the DataSource of your GridView.
Go to where the code is for your GridView in the Source tab and replace with the following code.
Code:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="Id" DataSourceID="SqlDataSource1">
<Columns>
<asp:HyperLinkField
DataNavigateUrlFields="News_Id"
DataNavigateUrlFormatString="~\newsdetails.aspx?News_Id={0}"
DataTextField="NewsHeadline"
HeaderText="News HeadLines"
SortExpression="NewsHeadline" />
</Columns>
</asp:GridView>
And you're all set. This will create a list of all the Headlines as hyperlinks with a dynamically generated unique link to the newsdetails.aspx page compliments of the query string we built using the PRIMARY KEY News_Id corresponding to each NewsHeadline entry in the NewsHeadline table.
Then when you load the newsdetails.aspx page you use: Request.QueryString["News_Id"] to get the News_Id value from the URL and use it to query the database for the details about the specific NewsHeadline that was clicked. You can then display the result of that query on the webpage.
The HyperLinkField will work great as others have pointed out. But, in case you want the entire row clickable, you can use a custom server control that implements a GridView suggested in the SO post "Making an entire row clickable in a gridview".
Check out the question I posted on how to implement a C# custom server control on implementing it.
Just another option.

Resources