Tuesday, August 31, 2010

Is the Back Button needed on Web Browsers

A friend recently was ranting about the Back button on a browser and that it often messes up pages he visits. A counterpoint argued that a good developer is always prepared for users to hit the back button and always programs to handle the user trying to go back in time.

As a web developer, I definitely agree that the Back button is a great nuisance. It also creates a layer of uncertainty in where your user is/came from when they arrive at a page. Anytime a user needs to be able to get back to page they came from, there should be an easily accessible link/button, so is the Back Button really needed?

I could foresee a lot of malicious intent if browsers didn't have a Back button. Maybe the true problem is how overused or available it is.

Maybe one alternative would be to present the user with a new tab for every new site (domain) they navigate to and remove the Back button. Each website is now responsible for the navigation around it's own site, yet if you ever pull up something you didn't actually want, you can easily close the tab and you're back at the site that sent you there. It's really just your web history presented different, but it would take up a shit load of memory (depending on the sites you had pulled up). I'm sure other problems would come from such a strategy as well.

I can't really think of a method that would keep you in full control of web surfing yet remove the Back button entirely. Feels like it might be a necessary evil that developers just have to accept and work around.

Friday, August 27, 2010

Nested Gridview Within Another Gridview

I recently came across a project for which I had a need for a gridview within a gridview.
For this example, I will create a grids of documents and guides housed within a parent grid of resource categories.

Let's start with a basic gridview of 4 documents (2 training modules on gridviews and 2 user manuals for cell phones).

<asp:GridView
ID="gvDocuments"
DataSourceID="dataDocuments"
AutoGenerateColumns="false"
DataKeyNames="document_id"
CellPadding="8"
HeaderStyle-BackColor="#e0e0e0"
BorderColor="#e0e0e0"
runat="server">
<Columns>
<asp:HyperLinkField
HeaderText="Resource Link"
DataNavigateUrlFields="document_filename"
DataNavigateUrlFormatString="{0}"
Target="_blank"
DataTextField="document_name"
DataTextFormatString="{0}" />
<asp:BoundField
DataField="document_description"
HeaderText="Description" />
</Columns>
</asp:GridView>
<asp:SqlDataSource
ID="dataDocuments"
runat="server">
</asp:SqlDataSource>


Both could be considered training, but to better organize the page, I will split the documents up into groups, each document having a group column in the database named document_group.
On my backend, I have a new table to complement the Documents table called DocumentGroups that has a docGrp_name and docGrp_id field. The docGrp_id field will link to the document_group column I mentioned.

Now to drop my original gridview in a second gridview of "Document Groups"
This is where the code gets a little more bloated but still relatively simple:
<asp:GridView
ID="gvDocumentGroups"
DataSourceID="dataDocumentGroups"
DataKeyNames="docGrp_id"
AutoGenerateColumns="false"
GridLines="None"
runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<div style="padding-bottom: 12px;">
<div><%#Eval("docGrp_name")%></div>
<asp:GridView
ID="gvDocuments"
DataSourceID="dataDocuments"
AutoGenerateColumns="false"
DataKeyNames="document_id"
CellPadding="8"
HeaderStyle-BackColor="#e0e0e0"
BorderColor="#e0e0e0"
runat="server">
<Columns>
<asp:HyperLinkField
HeaderText="Resource Link"
DataNavigateUrlFields="document_filename"
DataNavigateUrlFormatString="{0}"
Target="_blank"
DataTextField="document_name"
DataTextFormatString="{0}" />
<asp:BoundField
DataField="document_description"
HeaderText="Description" />
</Columns>
</asp:GridView>
<asp:SqlDataSource
ID="dataDocuments"
runat="server">
</asp:SqlDataSource>
</div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource
ID="dataDocumentGroups"
runat="server">
</asp:SqlDataSource>


I added in some padding for better spacing, but you can play around with the CSS however you want.

Now. I didn't put connection strings or select commands in the original SqlDataSource because, if you don't know what you're doing there, this tutorial is not for you.
But now that we've embedded this gridview inside another one, that (inner layer) SqlDataSource is more than likely going to be fed a variable from your outer layer grid.
For my purposes, I'm going to use the docGrp_id, which I conveniently fed into the DataKeys of my outer layer SqlDataSource.
For more information on pulling the current row's datakey, click here.

For Each thisRow As GridViewRow In gvDocumentGroups.Rows
CType(thisRow.FindControl("dataDocuments"), SqlDataSource).SelectCommand = "SELECT * FROM [Documents] WHERE [document_group] = '" & gvDocumentGroups.DataKeys(thisRow.RowIndex).Value & "'"
Next




And there you have it!

Friday, August 20, 2010

Word Wrap a Label in Windows Form Applications

I recent was spinning out a quick Windows Form application to help an orders team look up product information and found myself questioning how to wrap text in a label rather than have it venturing off the application into nowheresville.

As a web developer, I always assume my text will find its place within the boundaries of a panel or table cell, whatever medium houses it. But the same should not be assumed for Windows Forms applications. Luckily, there is a simple solution.

Set the label's AutoSize property to Off.

The label becomes a resizable control that you can drag to whatever limits you want the text contained within.