HowTo: Bind ASP.net control to list of files or folders
At ClipFlair Gallery metadata input pages for Activities and Clips I had to bind an ASP.net control to a list of files and folders respectively and although I found a Folder Contents DataSource control, it didn’t cover my needs (like filtering of a folder contents).
I just contributed my solution using .NET Anonymous Types and LINQ (assumes a using System.Linq clause) to:
http://stackoverflow.com/questions/1331793/bind-repeater-to-a-list-of-files-and-or-folders
private string path = HttpContext.Current.Server.MapPath("~/activity"); protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) { //only at page 1st load
listItems.DataSource = Directory.EnumerateFiles(path, "*.clipflair") .Select(f => new { Filename=Path.GetFileName(f) });
listItems.DataBind(); //must call this } }
The above snippet gets all *.clipflair files from ~/activity folder of a web project
Update: using EnumerateFiles (availabe since .NET 4.0) instead of GetFiles since this is more efficient with LINQ queries. GetFiles would return a whole array of filenames in memory before LINQ had a chance to filter it.
The following snippet shows how to use multiple filters, which GetFiles/EnumerateFiles don’t support themselves:
private string path = HttpContext.Current.Server.MapPath("~/image"); private string filter = "*.png|*.jpg"; protected void Page_Load(object sender, EventArgs e) { _listItems = listItems; if (!IsPostBack) { listItems.DataSource = filter.Split('|').SelectMany(
oneFilter => Directory.EnumerateFiles(path, oneFilter)
.Select(f => new { Filename = Path.GetFileName(f) })
); listItems.DataBind(); //must call this if (Request.QueryString["item"] != null) listItems.SelectedValue = Request.QueryString["item"];
//must do after listItems.DataBind } }
The snippet below shows how to get all directories from /~video folder and also filters them to select only directories that contain a .ism file (Smooth Streaming content) with the same name as the directory (e.g. someVideo/someVideo.ism)
using System; using System.IO; using System.Linq; using System.Web; using System.Web.UI.WebControls; namespace ClipFlair.Gallery { public partial class VideoMetadataPage : System.Web.UI.Page { private string path = HttpContext.Current.Server.MapPath("~/video"); protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { //only at page 1st load
listItems.DataSource = Directory.GetDirectories(path) .Where(f =>(Directory.EnumerateFiles(f,
Path.GetFileName(f)+".ism").Count()!=0)) .Select(f => new { Foldername = Path.GetFileName(f) }); //when having a full path to a directory don't use Path.GetDirectoryName //(gives parent directory), //use Path.GetFileName instead to extract the name of the directory listItems.DataBind(); //must call this } }
The examples above are from a DropDownList, but it’s the same logic with any ASP.net control that supports Data Binding (note I’m calling Foldername the data field at the 2nd snippet and Filename at the 1st one, but could use any name, need to set that in the markup):
<asp:DropDownList ID="listItems" runat="server" AutoPostBack="True" DataTextField="Foldername" DataValueField="Foldername" OnSelectedIndexChanged="listItems_SelectedIndexChanged" />