When you want to upload a file to the dnj site or the .text blog admin, a real Windows file open dialog pops. Quite cool and a piece of functionality I wanted for one of my own apps. Getting that done was, thanks to COM, easier than I had anticipated. So let me share this with you.
A (file)dialog in a webpage is run by the browser. It is client-side code and has to a snippet of script. Personally I am not a great fan of scripting (too many things can go wrong at runtime) so the script snippet should be as small as possible. From the server side code of a web-page you can inject snippets of script from your C# (or vb.net) code. The nice way of creating the script that way is that you can leave a lot of the decision logic on the server and generate the smallest snippet imaginable. What I want to do is start a dialog and copy the name of the chosen file into a textbox. The Javascript to do that :
<Script language=JavaScript>
function BrowseClick(){
var dialog = new ActiveXObject('MSComDlg.CommonDialog');
dialog.Filter = 'All files (*.*)|*.*| ';
dialog.MaxFileSize = 260;
dialog.ShowOpen();
document.forms[0]['TextBox1'].value = dialog.FileName;
return false;}
</Script>
The function creates a commondialog COM object which wraps up all funtionality and exposes the essentials to script. A larger story on all its possibilities is on MSDN, here I only set the required properties. The ShowOpen method of the COM object executes it after which the selected filename is copied into TextBox1.
This script is only added to the page if there is a chance that it will be run, that is in the selected item template of a datalist. In my code it is a part of the datalist's ItemDataBound event.
System.Text.StringBuilder sb = new System.Text.StringBuilder("<Script language=JavaScript> function BrowseClick(){");
sb.Append("var dialog = new ActiveXObject('MSComDlg.CommonDialog');");
sb.Append("dialog.Filter = 'Alle bestanden (*.*)|*.*| ';");
sb.Append("dialog.MaxFileSize = 260;");
sb.Append("dialog.ShowOpen();");
sb.Append(String.Format("document.forms[0]['{0}'].value = dialog.FileName;", TextBox1.ClientID));
sb.Append("return false;} </Script>");
The script function is built using a stringbuilder. To insert the correct name of the textbox I use the ClientID property of the textbox control. This is the ID of the control in the browser, inside a template of a datalist or datagrid this ID will read something like "DataList1__ctl4_TextBox1" instead of just "TextBox 1".
RegisterClientScriptBlock(scriptKey, sb.ToString());
The generated script is added to the page by a call to the RegisterClientScriptBlock method. After that it can be used by the controls.
ButtonLinkNaarDocumentatie.Attributes.Add("OnClick", "return BrowseClick();");
In the last line a click handler is added to a button. The clickhandler will call the registered scriptfunction. As that function returns a false the postback initiated with the buttonclick will be canceled. All processing is done on the client, there's no reason yet for any server involvement.
The main thing to watch is the casing of your script. JavaScript is, like C#, also case-sensitive.
Blog on,
Peter