I came across two awesome blog posts by Doug Nelson.
Optional Parameters for Stored Procedures
GridView Dissapointments
I just updated my
GridView without DataSourceControl DataSource
blog entry and all code to allow sort state and data to persist between page changes.
Updates:
GridView without DataSourceControl DataSource
GridView without DataSourceControl DataSource C# Code Download
GridView without DataSourceControl DataSource VB.NET Code Download
GridView without DataSourceControl DataSource C# Live Example
GridView without DataSourceControl DataSource VB.NET Live Example
I've discovered that using EnableSortingAndPagingCallbacks="true" without a DataSourceControl data source causes sorting not to work. While I don't know exactly why this happens, I'm hoping this blog entry will save a lot of people from banging their head on the table.
Update: I found the answer on
MSDN Bugs
.
I put together sample code that will run on the Northwind database that demonstrates using a generic List collection as a data source for an ObjectDataSource which populates a GridView control. All you have to do is specify the connection string in Web.config and the sample code will run. Enjoy.
Download C# ObjectDataSource Sample
Download VB.NET ObjectDataSource Sample
It appears that there is a security feature built-in to the HyperLinkField that causes links that resemble JavaScript functions (i.e. java script:SomeFunction()), file paths (i.e. F:\Directory\File), and other non-URL strings not to render when using the DataNavigateUrlFormatString property. The only way I've discovered around this is to use a TemplateField with a HyperLink control.
Will not render a URL:
<
asp
:
HyperLinkField
DataTextField
="SomeField"
DataNavigateUrlFields
="SomeField"
DataNavigateUrlFormatString
="java script:openWindow('/SomePage.aspx?SomeID={0}','SomeDescription','scrollbars=yes,width=442,height=500');"
/>
Will render a URL:
<
asp
:
TemplateField
>
<
ItemTemplate
>
<
asp
:
HyperLink
Text
='
<%# ((System.Data.DataRowView)Container.DataItem)["SomeField"] %>
'
NavigateUrl
='
<%# String.Format
("java script:openWindow('/SomePage.aspx?SomeID={0}','SomeDescription','scrollbars=yes,width=442,height=500');",
((System.Data.DataRowView)Container.DataItem)["SomeField"] as string) %>
'
runat
="server"
/>
ItemTemplate
>
asp
:
TemplateField
>
Below is a helper class that I use for exporting a DataGrids contents to an external file. The below code references gridViewText, but I haven't tested it out on a GridView yet as the code is from an application I'm working on upgrading. But, it works like a charm on the DataGrid.
public sealed class
ExportHelper
{
public static void
ExportToCsv(
string
gridViewText,
string
contentType,
HttpResponse
response)
{
const string
m_Delimiter_Column =
","
;
string
m_Delimiter_Row =
Environment
.NewLine;
response.ContentType = contentType;
Regex
m_RegEx =
new
Regex
(@
"(>\s+<)"
,
RegexOptions
.IgnoreCase);
gridViewText = m_RegEx.Replace(gridViewText,
"><"
);
gridViewText = gridViewText.Replace(m_Delimiter_Row,
String
.Empty);
gridViewText = gridViewText.Replace(
""
, m_Delimiter_Row);
gridViewText = gridViewText.Replace(
"
"
,
String
.Empty);
gridViewText = gridViewText.Replace(m_Delimiter_Column,
"\\"
+ m_Delimiter_Column);
gridViewText = gridViewText.Replace(
"
|
"
, m_Delimiter_Column);
m_RegEx =
new
Regex
(@
"<[^>]*>"
,
RegexOptions
.IgnoreCase);
gridViewText = m_RegEx.Replace(gridViewText,
String
.Empty);
gridViewText =
HttpUtility
.HtmlDecode(gridViewText);
response.Write(gridViewText);
response.End();
}
public static void
ExportToExcelWord(
string
gridViewText,
string
contentType,
HttpResponse
response)
{
response.ContentType = contentType;
response.Write(gridViewText);
response.End();
}
}
If you're like me and converting a .NET 1.1 application to 2.0, and aren't using a DataSourceControl DataSource just yet but need to enable sorting and paging, you might run into the following exceptions:
When changing the page:
The GridView 'GridViewID' fired event PageIndexChanging which wasn't handled.
When clicking a column name to sort the column:
The GridView 'GridViewID' fired event Sorting which wasn't handled.
As a result of not setting the DataSourceID property of the GridView to a DataSourceControl DataSource, you have to add event handlers for sorting and paging.
<
asp
:
GridView
ID
="gridView"
AllowPaging
="true"
AllowSorting
="true
"
OnPageIndexChanging
="gridView_PageIndexChanging"
OnSorting
="gridView_Sorting"
runat
="server" />
private
string
GridViewSortDirection
{
get
{
return
ViewState[
"SortDirection"
]
as
string
??
"ASC"
; }
set
{ ViewState[
"SortDirection"
] =
value
; }
}
private
string
GridViewSortExpression
{
get
{
return
ViewState[
"SortExpression"
]
as
string
??
string
.Empty; }
set
{ ViewState[
"SortExpression"
] =
value
; }
}
private
string
GetSortDirection()
{
switch
(GridViewSortDirection)
{
case
"ASC"
:
GridViewSortDirection =
"DESC"
;
break
;
case
"DESC"
:
GridViewSortDirection =
"ASC"
;
break
;
}
return
GridViewSortDirection;
}
protected
void
gridView_PageIndexChanging(
object
sender,
GridViewPageEventArgs
e)
{
gridView.DataSource = SortDataTable(gridView.DataSource
as
DataTable
,
true
);
gridView.PageIndex = e.NewPageIndex;
gridView.DataBind();
}
protected
DataView
SortDataTable(
DataTable
dataTable,
bool
isPageIndexChanging)
{
if
(dataTable !=
null
)
{
DataView
dataView =
new
DataView
(dataTable);
if
(GridViewSortExpression !=
string
.Empty)
{
if
(isPageIndexChanging)
{
dataView.Sort =
string
.Format(
"{0} {1}"
, GridViewSortExpression, GridViewSortDirection);
}
else
{
dataView.Sort =
string
.Format(
"{0} {1}"
, GridViewSortExpression, GetSortDirection());
}
}
return
dataView;
}
else
{
return
new
DataView
();
}
}
protected
void
gridView_Sorting(
object
sender,
GridViewSortEventArgs
e)
{
GridViewSortExpression = e.SortExpression;
int
pageIndex = gridView.PageIndex;
gridView.DataSource = SortDataTable(gridView.DataSource
as
DataTable
,
false
);
gridView.DataBind();
gridView.PageIndex = pageIndex;
}
This is a common issue even with the DataGrid control. PostBack is invoked and your GridView doesn't update or, in some cases, disappears. All you need to do is force the GridView to bind to its datasource by calling the DataBind() method, GridView.DataBind(), where GridView is the placeholder for the control ID of the GridView control.
R
Another common question I see on forums and lists is how to get the content of a GridView cell when in Edit mode. The following code demonstrates how to get the text of a cell at index position 3 using an OnEditing event.
VB.NET
Private Sub
GridView_RowEditing(
ByVal
sender
As Object
,
ByVal
e
As
GridViewEditEventArgs)
Dim
m_RowIndex
As Integer
m_RowIndex = e.NewEditIndex
Dim
m_ColumnText
As String
m_ColumnText = GridViewID.Rows(m_RowIndex).Cells(3).Text
End Sub
C#
private void
GridView_RowEditing(
object
sender,
GridViewEditEventArgs
e)
{
int
m_RowIndex;
m_RowIndex = e.NewEditIndex;
string
m_ColumnText;
m_ColumnText = GridViewID.Rows[m_RowIndex].Cells[3].Text;
}
R
The .NET Framwork 2.0 introduces
Eval()
.
Eval()
is a shortcut for
Container.DataItem()
. Since
Eval()
uses Reflection, it causes overhead. From a optimization standpoint, it is better to use
Container.DataItem()
.
VB.NET
Container.DataItem()
C#
DataReader:
((System.Data.Common.DbDataRecord)Container.DataItem)[]
DataSet:
((System.Data.DataRowView)Container.DataItem)[]
R
Lets say you have multiple DataKeys assigned to the DataKeyNames property of the GridView control where only one DataKey will have a value and the rest will be null. Based on the non-null value, you want to trigger a conditional. I've discovered an easy to accomplish this is using Reflection and a GridView event. In this example, the value of my DataKeys are all of type integer.
VB.NET
Private Sub
GridView_Created(
ByVal
sender
As Object
,
ByVal
e
As
GridViewRowEventArgs
)
If
e.Row.RowType = DataControlRowType.DataRow
Then
Dim
nKeyVal
As Integer
If
g
ridView.DataKeys(e.Row.RowIndex).Values(
"K
eyName1"
).GetType() ==
Type
.GetType(
"System.Int32
"
)
Then
nKeyVal =
g
ridView
.DataKeys(e.Row.RowIndex).Values
(
"K
eyName1"
)
' Do something
End If
If
g
ridView.DataKeys(e.Row.RowIndex).Values
(
"K
eyName2"
).GetType() ==
Type
.GetType(
"System.Int32
"
)
Then
nKeyVal =
g
ridView
.DataKeys(e.Row.RowIndex).Values
(
"K
eyName2"
)
' Do something
End If
If
gridView.DataKeys(e.Row.RowIndex).Values
(
"K
eyName3"
).GetType() ==
Type
.GetType(
"System.Int32
"
)
Then
nKeyVal =
gridView
.DataKeys(e.Row.RowIndex).Values(
"K
eyName3"
)
' Do something
End If
End If
End Sub
C#
private
void
GridView_Created(
object
sender,
GridViewRowEventArgs
e)
{
if
(e.Row.RowType == DataControlRowType.DataRow)
{
int
nKeyVal;
if
(
g
ridView.DataKeys[e.Row.RowIndex].Values[
"K
eyName1"
].GetType() ==
Type
.GetType(
"System.Int32
"
))
{
nKeyVal = (
int
)
g
ridView
.DataKeys[e.Row.RowIndex].Values[
"K
eyName1"
];
// Do something
}
if
(
g
ridView.DataKeys[e.Row.RowIndex].Values[
"K
eyName2"
].GetType() ==
Type
.GetType(
"System.Int32
"
))
{
nKeyVal = (
int
)
g
ridView
.DataKeys[e.Row.RowIndex].Values[
"K
eyName2"
];
// Do something
}
if
(gridView.DataKeys[e.Row.RowIndex].Values[
"K
eyName3"
].GetType() ==
Type
.GetType(
"System.Int32
"
))
{
nKeyVal = (
int
)
gridView
.DataKeys[e.Row.RowIndex].Values[
"K
eyName3"
];
// Do something
}
}
}
Note:
gridView is the ID of the GridView control.
R
O DataKeyNames, Where Art Thou?
The GridView control has a cool feature that allows you to bind more than one value as a DataKey. However, the documentation that I could find on how to get a DataKey other than the primary key was sparse. I finally discovered:
VB.NET
GridView.DataKeys(Index1).Values(
Index2)
C#
GridView.DataKeys[Index1].Values[
Index2
]
Where GridView is the ID of the GridView control, Index1 is the index of the row in the GridView, and Index2 is the name of the DataKey.
R
Here is something that many people may not know about GridView paging: Interface paging, the method of paging used by the GridView control, causes all your data to be loaded into memory at the time the data binds to the GridView. This means that if you are returning a huge amount of records, you will impose a huge performance constraint on your server. What is the solution? The ObjectDataSource offers data source paging.
For more information on the ObjectDataSource, visit
http://tinyurl.com/qfykh
.
R
More Posts
Next page »
|