Fun with Telerik Rad Controls (Part 3/5)

by ManniAT 11. April 2009 06:27
Technorati-Tags:

In the first part I showed the implementation of the backup logic, the second part was about integration with the a Custom File Content Provider.

You remember:

  1. Backup functionality (make copies of deleted / overwritten files)  (DONE)
  2. Copy files with drag and drop (the control does a move for this) (DONE)
  3. Protect files from being deleted (DONE)
  4. Add server side events when a file / directory is selected (the control is almost pure client Ajax)

The events…

The telerik RadFileExplorer is an Ajax control. This means – everything runs at the client :)
Of course it does not – but there is little communication and (with the current version) there are only server events available for things like deleting a file or so.

Or let me tell it the other way – exactly the things I’m interested in do not fire server events.

So I first took a look at the client events and there I found what I needed. The telerik RadFileExplorer has a rich client event model and so it was easy to find the two events I was looking for.

All I had to do was to handle these events and route them to the server.
So it comes to java script (I prefer C# :)):

Snippet created with CBEnhancer
<script language="javascript" type="text/javascript">
    //<![CDATA[
    var bIsRefreshing = false;
    function RefreshAfterFileRestore(sender, args) {
        setTimeout("TimerEnd()", 600); //used to avoid request while other request is still in progress
    }
    function TimerEnd() {
        bIsRefreshing = true; //block double refreshes
        var fX = $find("<%= rfxFiles.ClientID %>");
        fX.refresh(fX.get_currentDirectory());
    }

    function OnFolderLoaded(sender, args) {
        if (bIsRefreshing) {    //avoid refresh when initiated from a refresh
            bIsRefreshing = false;
            return;
        }
        var item = args.get_item();
        //inform the server that a new directory is the current one
        TellServerAboutSelectedElement("DIR:" + item.get_path()); //signal dir got loaded
    }
    function OnClientItemSelected(sender, args) {
        var item = args.get_item();
        if (item.get_type() == Telerik.Web.UI.FileExplorerItemType.File) {
            args.set_cancel(true);
            TellServerAboutSelectedElement("FILE:" + item.get_path());
        }
        else {
            //if you want the directory selected in grid as "current directory do this
            //TellServerAboutSelectedElement("DIR:" + item.get_path()); //signal no file selected!!
            //in this case I just want to tell that no file is selected
            TellServerAboutSelectedElement("FILE:");
        }
    }
    //not active - setting the element in page load is commented out
    function ResponseEnded(sender, args) {
        var v = args.EventTargetElement;
    }
    function RequestStarted(sender, args) {
        var v = args.EventTargetElement;
    }

    function TellServerAboutSelectedElement(argument) {
        var ajaxManager = $find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>");
        ajaxManager.ajaxRequest(argument);
    }
    //]]>
</script>

This may look a bit complicated – but it isn’t.
First of all – ignore the RefreshAfterFileRestore and TimerEnd functions – I’ll explain them later.

There are two interesting events here – OnFolderLoaded (the FileExplorer displays a new folder) and OnClientItemSelected (the user clicked on a file or folder).

In the case of a folder load I simply pass “DIR: FolderPath” to the server.
If an other Item is selected I pass either the filepath or an empty path for the file if the user selected a folder.

The reason – files are different – they can be previewd or things like this while folders are (in my case) not interesting as long as they are not opened. If someone thinks different – the code to handle selected folders is here in comments.

The server communication function is easy since telerik offers a thing called RadAjax – a framework which makes it very easy to handle Ajax things.

What I do here – I get the RadAjaxManager control and call a function which makes an Ajax Request to the server.

On the Server the things look like this:

protected void OnControlsl_AjaxRequest(object sender, Telerik.Web.UI.AjaxRequestEventArgs e) {
    if (e.Argument.StartsWith("FILE:")) {
        CurFile = e.Argument.Replace("FILE:", "");    //keep selection in hiden form file
        RaisePostBackEvent("FILE");
    }
    else {    //if it is not a file it must be directory
        CurDir = e.Argument.Replace("DIR:", "");    //keep selection in hiden form file
        RaisePostBackEvent("DIR");
        CurFile = "";    //no file selected after loading a directory
        RaisePostBackEvent("FILE");    //signal that file did change
        rgBackupFiles.Rebind();    //and load backup files for this directory
    }
}

This is the server side function which get’s call via Ajax. I do the following – if a file is selected I store it’s path.
If a folder is selected there is no file selected – so I clear the file and store the directory.

Important – to preserve these values among postbacks I use hidden controls so the values are kept in viewstate.

You may have noticed that I call a function “RaisePostBackEvent” – this is the bridge to the events my control fires.

    #region event handling
    #region FileSelected
    public event EventHandler FileSelected;
    #endregion
    #region DirectorySelected
    public event EventHandler DirectorySelected;
    #endregion
    #region IPostBackEventHandler Member
    public void RaisePostBackEvent(string eventArgument) {
        if (eventArgument == "FILE") {
            OnFileSelected(new EventArgs());
            return;
        }
        OnDirSelected(new EventArgs());
    }
    protected virtual void OnFileSelected(EventArgs e) {
        if (FileSelected != null) {
            FileSelected(this, e);
        }
    }
    protected virtual void OnDirSelected(EventArgs e) {
        if (DirectorySelected != null) {
            DirectorySelected(this, e);
        }
    }
    #endregion
    #endregion

 

This is the complete event handling. It is done by implementing the IPostBackEventHandler interface (one function :=)) and the rest is “event handling as usual”. Check if the handler has a consumer – if so fire the event.

In the Ajax handler is a code line

        rgBackupFiles.Rebind();    //and load backup files for this directory
    }
}

Yes – I did not explain it – this rebinds a datagrid – because – backup files is one idea – restore them makes the thing useful.
But I’ll describe this in the next post.

Let me first finish here and show how the control is used – and how the events are consumed.

Snippet created with CBEnhancer
<uc1:XFileExplorer ID="xfeOne" runat="server"
BackupURL="/XBackup"
BackupEnabled="True"
DoCopy="True"
ProtectedFiles="/XFiles/Styles/XFEStyles.css,/XFiles/Styles/Main.css,/XFiles/Styles/bkg/PageBKG.jpg"
ViewPaths="~/XFiles,~/XImages,~/XDocs"
DeletePaths="~/XFiles,~/XImages,~/XDocs"
UploadPaths="~/XFiles,~/XImages,~/XDocs"
OnFileSelected="xfeOne_OnFileSelected"
OnDirectorySelected="xfeOne_OnDirSelected" />

This control is hosted in an aspx page.

The last Line contains the event binding and before I make those settings I told before – BackupEnabled, ProtectedFiles and so on.
By the way – ViewPaths, DeletePaths and UploadPaths are original properties from the telerik RadFileExplorer  which I simply pass to this control which I host in my usercontrol.

Now as the events are bound here – lets have a look how they are consumed.
But first I have to show the other controls on this page (just a sample that these events make sense):

Snippet created with CBEnhancer
<tr>
    <td style="width: 300px;text-align:center;font-weight:bold;background-color:#E0E0E0">
        Current directory
    </td>
    <td style="width: 220px;text-align:center;font-weight:bold;background-color:#E0E0E0">
        Current file
    </td>
</tr>
<tr>
    <td style="width: 300px;">
        <asp:Label ID="lblCurDir" runat="server" />
    </td>
    <td style="width: 220px;">
        <asp:Label ID="lblCurFile" runat="server" />
    </td>
</tr>
<tr>
    <td style="width: 300px;">
        <asp:HyperLink ID="hlZIPDir" runat="server" Visible="false" NavigateUrl="/DoDownload.ashx?Action=DIR" Text="Download Directory as ZIP" Target="_blank" />
    </td>
    <td style="width: 220px;">
        <asp:HyperLink ID="hlDownloadFile" runat="server" Visible="false" NavigateUrl="/DoDownload.ashx?Action=FILE" Text="Download File" Target="_blank" />
    </td>
</tr>
<tr>
    <td style="text-align:center" colspan="2">
        <asp:Image ID="imgPreview" runat="server" Visible="false"/>
    </td>
</tr>

This is part of a table holding two labels to display the current directory and file (selected in FileExplorer) as well as two hyperlinks to a http handler which handles the download of files / folder ZIPs.

Now let us take a look at the server side.

protected void xfeOne_OnFileSelected(object sender, EventArgs e) {
    string strCurFile = xfeOne.CurFile;
    lblCurFile.Text =strCurFile;
    if (string.IsNullOrEmpty(strCurFile)) {
        //clear parameter for download handler
        Session["CurFile"] = null;
        hlDownloadFile.Visible = false;
        imgPreview.Visible = false;
        return;
    }
    hlDownloadFile.Visible = true;
    Session["CurFile"] = strCurFile;
    //try to set preview for images
    string strExtension = Path.GetExtension(strCurFile).ToUpper();
    if (strExtension == ".PNG" || strExtension == ".JPG" || strExtension == ".GIF") {
        imgPreview.ImageUrl = strCurFile;
        imgPreview.Visible = true;
    }
    else {
        imgPreview.Visible = false;
    }
}
protected void xfeOne_OnDirSelected(object sender, EventArgs e) {
    string strCurDir = xfeOne.CurDir;
    lblCurDir.Text = strCurDir;
    if (string.IsNullOrEmpty(strCurDir)) {
        Session["CurDir"] = null;
        hlZIPDir.Visible = false;
        return;
    }
    hlZIPDir.Visible = true;
    Session["CurDir"] = strCurDir;
}

Very simple handlers – of course it is a sample to show the control  nothing more.
Those handlers check if there is a value (remember – file can be empty if the user selectes a folder).

Then I remember the values in session set the labels  – and show (hide) the links to the handler.
And if it is an image file – I set the value of the image control to display it.

So far we have a control looking like this one and a few “informational” controls for the current paths.
And we have “magic” behind the thing – backup / protection / copy instead of move.

We are almost done – but of course backup makes no sense when there is no restore.

I’ll describe this in the next section – and this will also give an answer to the question about the two JScript functions shown (but not explained) above.

Tags:

telerik

Pingbacks and trackbacks (1)+

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


Powered by BlogEngine.NET 2.0.0.0