Introduction
In some web projects I had to implement a configuration user interface containing a remote file selecting action - a file stored on a remote repository. For the first time, I did a simple ASPX page, but soon after I needed it in another ASPX page and I found a the user control would be a better solution. Furthermore it was a good opportunity to develop an interesting web custom control and apply it in an application.
Background
User controls are an easy kind of custom controls. They can be created as simply as creating an ASP.NET web page, using the Visual Studio Toolbox for designing and the code behind for defining properties and methods for the control. They can be then included in your ASP.NET web pages, using only the public members for input/output operations. All internal actions are encapsulated in the control and are not visible from the outside. You can't damage the - in some cases - very complex layout, which you designed with several hours of troublesome work. You can define other properties, e.g., to change the background or the forecolor properties of the control.
Using the code
The user control has been designed as an Explorer-like file browser, allowing the setting of access credentials, the start (root) directory, and finally selecting a file for any custom action. It consists, for the most part, a TreeView
control for browsing directories and a ListView
control for browsing files. The layout of the user control is determined by a CSS file.
The design of the custom control:
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="FileBrowser.ascx.cs" Inherits="FileBrowser" %>
<link href="../Stylesheets/FileBrowser.css" rel="stylesheet" type="text/css" />
<div id="browserContent" >
<table id="tableMainContent" runat="server"
class="mainContent" cellspacing="2" cellpadding="2">
<tr style="text-align: left; vertical-align: top;">
<td class="folderColumn">
<div id="folderList" runat="server" class="folderPanel">
<table id="tableFolders" style="width:230px; "
cellspacing="0" cellpadding="0" runat="server">
<tr id="trHeader" class="fileListHeader" runat="server">
<td id="tdFolderHeader1" class="folderListHeaderCell1" runat="server">
<asp:LinkButton ID="Button_Parent" runat="server"
OnClick="Button_Parent_Click" Text="[..]" />
</td>
<td id="tdFolderHeader2" class="folderListHeaderCell2" runat="server">
</td>
</tr>
</table>
<asp:Panel ID="Panel_FolderList" runat="server"
Height="284px" ScrollBars="Auto">
<asp:ListView ID="ListView_Folders" runat="server"
OnSelectedIndexChanging="ListView_Folders_SelectedIndexChanging"
ConvertEmptyStringToNull="False" EnableModelValidation="True">
<LayoutTemplate>
<table id="tblFolders" runat="server" class="folderList"
cellspacing="0" cellpadding="0">
<tr runat="server" id="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id="Tr1" class="rowUnselected" runat="server">
<td>
<asp:LinkButton ID="Button_Name" runat="server"
CommandName="Select" ToolTip='<%#Eval("FullName") %>'
Text='<%#Eval("Name") %>' />
</td>
</tr>
</ItemTemplate>
<SelectedItemTemplate>
<tr id="Tr2" class="rowSelected" runat="server">
<td>
<asp:LinkButton ID="Button_Name" runat="server"
CommandName="Select" ToolTip='<%#Eval("FullName") %>'
Text='<%#Eval("Name") %>' />
</td>
</tr>
</SelectedItemTemplate>
<EmptyItemTemplate>
<td>
<asp:LinkButton ID="Button_Parent" runat="server"
OnClick="Button_Parent_Click" Text="[..]" />
</td>
</EmptyItemTemplate>
</asp:ListView>
</asp:Panel>
</div>
</td>
<td class="filesColumn">
<div id="fileList" runat="server" class="filesPanel">
<table id="Table_Attr" cellspacing="0" cellpadding="0" runat="server">
<tr id="Tr2" class="fileListHeader" runat="server">
<td id="tdFilesHeader1" runat="server" class="fileListHeaderCell1">
<asp:Label ID="Label_Name" runat="server" Text="Name" />
</td>
<td id="tdFilesHeader2" class="fileListHeaderCell2" runat="server">
<asp:Label ID="Label_Size" runat="server" Text="Size" />
</td>
<td id="tdFilesHeader3" class="fileListHeaderCell3" runat="server">
<asp:Label ID="Label_LastWriteTimeUtc" runat="server" Text="LastChanged" />
</td>
</tr>
</table>
<asp:Panel ID="Panel_FileList" runat="server" Height="284px" ScrollBars="Auto">
<asp:ListView ID="ListView_Files" runat="server"
OnSelectedIndexChanging="ListView_Files_SelectedIndexChanging"
ConvertEmptyStringToNull="False" EnableModelValidation="True">
<LayoutTemplate>
<table class="folderList" cellspacing="0"
cellpadding="0" runat="server" id="tblFiles">
<tr runat="server" id="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id="Tr1" class="fileUnselected" runat="server">
<td style="width: 342px;">
<asp:LinkButton ID="Button_Name" runat="server" ToolTip='<%#Eval("FullName") %>'
CommandName="Select" Text='<%#Eval("Name") %>' />
</td>
<td style="width: 80px;">
<asp:Label ID="Label_Size" runat="server" Text='<%#Eval("Length") %>' />
</td>
<td style="width: 130px;">
<asp:Label ID="Label_LastWriteTimeUtc" runat="server"
Text='<%#Eval("LastWriteTimeUtc") %>' />
</td>
</tr>
</ItemTemplate>
<SelectedItemTemplate>
<tr id="Tr2" class="fileSelected" runat="server">
<td style="width: 342px;">
<asp:LinkButton ID="Button_Name" runat="server" ToolTip='<%#Eval("FullName") %>'
CommandName="Select" Text='<%#Eval("Name") %>' />
</td>
<td style="width: 80px;">
<asp:Label ID="Label_Size" runat="server" Text='<%#Eval("Length") %>' />
</td>
<td style="width: 130px;">
<asp:Label ID="Label_LastWriteTimeUtc" runat="server"
Text='<%#Eval("LastWriteTimeUtc") %>' />
</td>
</tr>
</SelectedItemTemplate>
<EmptyItemTemplate>
<td id="Td1" runat="server">
</td>
</EmptyItemTemplate>
</asp:ListView>
</asp:Panel>
</div>
</td>
</tr>
</table>
</div>
The public properties of the FileBrowser
control defined in the code-behind file:
public string UserName
{
get { return ViewState["UserName"].ToString(); }
set { ViewState["UserName"] = value; }
}
public string UserDomain
{
get { return ViewState["UserDomain"].ToString(); }
set { ViewState["UserDomain"] = value; }
}
public string UserPassword
{
get { return ViewState["UserPassword"].ToString(); }
set { ViewState["UserPassword"] = value; }
}
public FileInfo SelectedFile
{
get { return (FileInfo)ViewState["SelectedFile"]; }
private set { ViewState["SelectedFile"] = value; }
}
public string CurrentFolder
{
get { return ViewState["CurrentFolder"].ToString(); }
set { ViewState["CurrentFolder"] = value; }
}
public string RootFolder
{
get { return ViewState["RootFolder"].ToString(); }
set { ViewState["RootFolder"] = value; }
}
The property values are saved in ViewState variables.
Using the control
The control can be simply referenced in your web page using the Register
directive:
<%@ Register TagPrefix="fb" TagName="FileBrowser" Src="~/UserControls/FileBrowser.ascx" %>
and finally embedded into your web page:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="Stylesheets/FileBrowser.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server" style="width: 800px;">
<asp:ToolkitScriptManager ID="ScriptManager1" runat="server">
</asp:ToolkitScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div>
<fb:FileBrowser ID="FileBrowser1" runat="server"
OnSelectedFileChanged="FileBrowser1_SelectedFileChanged" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
<div>
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="FileBrowser1" EventName="SelectedFileChanged" />
</Triggers>
<ContentTemplate>
<div style="height: 100px;vertical-align:middle;">
Selected file: <asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
I've used here two UpdatePanel
controls from the AJAX Control Toolkit for better touch-and-feel of the file browser control. You can remove it, or replace it with another JavaScript based framework.
The initial values of the input properties are set preferably in the web.config file:
<appSettings>
<add key="FileBrowserUserName" value="IOuser"/>
<add key="FileBrowserUserDomain" value="IOdomain"/>
<add key="FileBrowserUserPwd" value="IOpassword"/>
<add key="FileBrowserInitialPath" value="C:\"/>
</appSettings>
You have to certainly replace the placeholders with valid user credentials. The user must have read access for the target file system.
For using the control in your web page, you have to set the initial properties in the Page_Load
event handler and implement the SelectedFileChanged
event handler in your code-behind file:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
FileBrowser1.UserName =
WebConfigurationManager.AppSettings["FileBrowserUserName"];
FileBrowser1.UserDomain =
WebConfigurationManager.AppSettings["FileBrowserUserDomain"];
FileBrowser1.UserPassword =
WebConfigurationManager.AppSettings["FileBrowserUserPwd"];
FileBrowser1.CurrentFolder =
WebConfigurationManager.AppSettings["FileBrowserInitialPath"];
FileBrowser1.RootFolder = FileBrowser1.CurrentFolder;
FileBrowser1.Refresh();
}
}
protected void FileBrowser1_SelectedFileChanged(object sender, EventArgs e)
{
Label1.Text = FileBrowser1.SelectedFile.FullName;
}
And voilĂ , that's all folks.
History
- 2011-12-16: Initial release.