Shukhrat Nekbaev

Customizing RadTreeView: adding custom context menu trigger



I have Telerik's RadTreeView control used on a page, it has a context menu for every node triggered by the right click, recently a change request arrived saying that it's not obvious for user that there a context menu there (that right click on node actually does something), so let's add also a custom trigger, let it appear when when user hovers node item and when clicked (left clicked) let it show the context menu for node item.

<img/> tag was chosen as trigger with "gear" as source image. Also when item is too long and RadTreeView has horizontal scroll (node's text doesn't fit and tree control's size is fixed) I needed to "gear" in rightmost position over node's text, if item's text is short enough, then increase it's size and show "gear" nearby, etc misc usability issues. 


I've implemented solution by handling client side events from rad controls. Solution has 2 pages: RadTreeViewAbsolute and RadTreeViewRelative which show how to accomplish the task using absolute and relative positioning. Note that for both types of positioning slightly different approaches were used:

  • absolute looks great, but a bit heavy, cause I also attach 'scroll' event handle to parent container that has vertical scroll (otherwise when item is hovered and user scrolls with the mouse wheel "gear" element will remain in old position, so I hide it in this event).
  • relative on the other hand just plays with left margin value (and additional values from margins and paddings of base dom structure of node item);

Pages use different css classes, main difference is treeGear class.

If your image will be of a different size adjust <img/> tag in <NodeTemplate>, treeGear class for corresponding positioning (to align vertically) and these two:

sender.PGC_imageSize = 13; <-- set image width value here
sender.PGC_extraMarginBeforeImage = 5; <-- set a value which is a margin between node item's text and "gear" element.

Note that when you click on "gear" highlighting of node item may disappear. This will happen if EnableDragAndDrop is not set or false. I haven't thought how to solve that because in my use case I have EnableDragAndDrop="true", but I will ask Telerik support about possible solution. 

Note also that when <NodeTemplate> is used some events are triggered more than once, I observed that with mouse over and mouse out events, this is why (most likely) in relative positioning sometimes when "gear" element is hovered it may slightly reposition itself :)


Choose yourself which approach fits better to your solution.

Source code:

Screenshot: RadTreeView with gears

Implementing a custom CSS stylesheet manager and taking advantage of caching


this post will provide brief overview why and how I have implemented "basic" custom stylesheet manager. Note that even post will be related to solving Telerik related issue it's not binded to it, this approach could be used in your solutions that don't use Telerik at all. Sources are attached.


I'm developing a ASP.NET 4.0 WebForms application which is fully ajaxified and uses Telerik controls, one of issues I ran into at first was that when you load certain Telerik control dynamically it might have missing styles or images. Digging Telerik forums hinted that I should preload CSS for controls I load dynamically, one of approaches was direct call of GetWebResourceUrl method, well, I also wanted to opmitize things, so I utilized Telerik's RadStyleSheetManager which basically can combine and compress all your CSS in one file which is a good thing. That was what I wanted: I globally (in web.config) disabled loading of skins and base stylesheets for Telerik controls, because I was preloading those myself in RadStyleSheetManager. Everything was charming unless I wanted to use LinkManager, which is an additional built-in dialog for managing URLs for RadEditor: when loaded it was totally unstyled. Reason that dialog wasn't loading style was that I turned off loading of skins and css for all Telerik controls. Though RadEditor has property called DialogsCssFile I wasn't happy with that approach. What it does is you specify custom css file into that property and that css file would have set of css @import directives to preload required css files for that dialog. Basically that was saying: buddy, you wanted to optimize preloading of styles using RadStyleSheetManager, but in that case you will have to load styles "old way" (separate <link/> to every file), more over that means that I will need to copy those css and used images (for Telerik controls utilized inside LinkManager) from Telerik's installation folder to my WebApp. That was a last drop.

I have to mention here that I also wanted to customize LinkManager, so I followed example from their SDK on how to customize built-in dialogs.

I verified that indeed setting DialogsCssFile for RadEditor object results into rendering single <link/> tag in header of iframe container, so I thought that I could benefit from that.

Note: you can't use RadStyleSheetManager inside LinkManager.ascx, it will throw an exception saying that RadStyleManager is already defined (in my case in my master page)


I decided to get rid of RadStyleSheetManager. My use case was simple: I needed to preload css for all controls I use + my own css for WebApp itself, also I wanted to use preloaded set of css for external dialogs. I've checked web and found SquishIt library, which was able to compress everything and render as a single file with hash in it's name, also it could utilize embedded resources. I gave it a try and soon figured out that it's not what I wanted: I had to give explicit permissions for Network Service account to be able to write into my css folder (because SquishIt wants to create a file) and currently it doesnt support WebResource attribute's PerformSubstitution property, meaning that resource references defined inside Telerik styles won't work.

So I've implemented custom css manager. It's very draft, simple, but suits my needs. What it does is when initialized it caches all the referenced css files (e.g.: in css folder and embedded), performs proper processing of PerformSubstitution property and compresses result using AjaxMin. Next in WebApp you call  a static method which generates a link to custom handler with calculated hash. This handler serves css content and get cached on client and server. Hash changes when you modify css content.

Concept behind are groups of css references. You can create a group called telerikDialogs and reference there only those css that are used by Telerik dialogs, same way you can create a group named telerikDialogs and reference there all styles for all controls that are used in your WebApp, same for main styles. You can also copy styles from one group to another. Main point is: do that once, even though it won't let you do it twice :) All initialization should happen once, yes, might not be handy in certain scenarios, but I think currently it fits perfectly most of use cases (of course feel free to adjust).

Example of how you reference:


CssReferenceManager.AddEmbeddedReference("Telerik.Web.UI.RadToolBar, Telerik.Web.UI", "Telerik.Web.UI.Skins.ToolBar.css");
CssReferenceManager.AddEmbeddedReference("Telerik.Web.UI.RadToolBar, Telerik.Web.UI", "Telerik.Web.UI.Skins.Default.ToolBar.Default.css");
CssReferenceManager.AddEmbeddedReference("Telerik.Web.UI.RadButton, Telerik.Web.UI", "Telerik.Web.UI.Skins.Button.css");



first you set a name for a group, then you add references, if you need another group (provide different name and add references. To perform actual processing call:

that would do that job and cache. Next in your master page or where you reference to css files put this:

<%= CssReferenceManager.GetHandlerUrlWithLinkTag("default") %>

this line will result in <link/> tag with reference to handler (which should be registered in web.config).

If you will get exception saying that controls collection can't be modified due <% %> tags wrap this call into RadScriptBlock

<telerik:RadScriptBlock ID="rsb1" runat="server">
        <%= CssReferenceManager.GetHandlerUrlWithLinkTag("default") %>

Please refer attached project with sources of StaticStyleSheetManager and test WebApp.


One of possible solutions to: Visual C++ 2008 Redistributable installation error 1935 with HRESULT 0x8007005


this post is slightly offtopic, but I'd like to share this experience because this might be a reason why Visual Studio or any other application that needs Visual C++ redistributable libraries fail during installation.  


I've used DriverCleaner on a PC with this issue to clean ATI drivers on my TouchSmart, later I tried installing Windows 7 SP1 which was failing with famous: Windows 7 SP1 Installation error 0x800f0826. This was solved by copying missing files from another Windows 7 PC (forums have instructions about that), but *main* point here is to be able to copy those files you need to take ownership of Windows\winsxs folder from TrustedInstaller and then restore for TrustedInstaller (I can hardly recall now, but most likely I also did replace permissions defined for window\winsxs to all it child items). Also I installed System Update Readiness Tool for Windows 7 at that time,  anyways, I managed to install SP1.

Time has passed, updates were being installed automatically, but one day in summer I've noticed that Security Update for Visual C++ 2008 Redistributable is failing to install. I tried to download it separately and install but was getting installation error for Microsoft.VC90.ATL assembly with error code 1935 and HRESULT 0x8007005.

I figured out that HRESULT 0x8007005 stands for "Access denied" and whole installation process was obviously related to Windows\winsxs folder. As soon as I knew I've touched it, I decided to check out how to properly restore permissions to that folder.

Note that uninstalling .NET 3.5.1, no sfc /scannow, no System Update Readiness Tool, no built in to Windows troubleshooter for update related problems could solve it. I also had some .NET installation verifier application, which found no errors.


has following post from user muuzzi dated: 2 Jun 2008 8:48 PM

Hi V!ctor and Astebner, I encountered the same problem while installing VS 2008 in my Vista.

I noticed there was a folder InstallTemp inside Winsxs. Do you ever changed the owner and permissions of Winsxs folder? (Weeks ago I changed the permissions to compress the Winsxs folder.) If so, you may not set the permission correctly. The most important thing is: The two folders - winsxs and winsxs\installtemp - have different permissions! InstallTemp should be granted Full Control to System and Administrators. If not, the setup program could not write vc80 dlls or vc90 dlls into the folder.
After I re-set the correct permissions, and run SFC.EXE /scannow to repair the consistency of system files, the setup of VS 2008 succeeded.

I've highlighted most inportant part. As soon as I knew that I was messing around with permissions I decided to check out, indeed that have different permissions and owners.To be able to modify Windows\winsxs folder I assigned ownership to Administators group (set check box to replace ownership to all child items also, otherwise you will not be able to modify permission settings for InstallTemp folder). Now edit permissions for InstallTemp (it will be inheriting from parent, uncheck that setting, dialog will popup about what to do with current parent permissions, choose "Add", that will explicitly define these permissions for that folder), define:

1)Full control to SYSTEM

2)Read & execute, List folder contents, Read, Write for Administrators group

3)Read for Users group

Save and verify that indeed this folder now has it's own set of permissions. Next step is to revert ownership to Trusted installer: open security settings for Windows\winsxs folder and change ownership from current Administrators group to TrustedInstaller (NETWORK SERVICE\TrustedInstaller), don't forget to check setting to replace ownership also for all child elements. When this all done Windows\winsxs and all child folders (except InstallTemp) would have same permissions and InstallTemp would have it's own set.

You can always refer to another Windows 7 PC for detailed comparison of permissions.

I ran sfc /scannow just in case, tried to install vcredist and success, in Windows Update I clicked "Check for updates" and it suggested me to install Security update again but this time file size was different (I feel like my vcredist was newer), tried it said: failed to install, I clicked "Try again" and it was successful. Reboot, "Check for updates" - you Windows is up to date message, nice :)

That's it :)

Adjusting Telerik RadTreeList to display visually separated items with depth level margins

Hi, in this post I would like to brief you how to make RadTreeList visually render like that (separated items depending on their level):

This could be usefull in scenarios of comment threads, where you would like to show all the comments expanded and highlight with different (main and alternative) color each of comment threads.

Consider comment thread as comment starting at root level with possbile child elements. Icons you see here are not native, but you can easily customize those.

I cleaned and removed extra stuff from my own sample, so here you go the template:

<telerik:RadTreeList ID="radListComments" runat="server" DataKeyNames="ID_HERE"
            ParentDataKeyNames="PARENT_ID_HERE" AutoGenerateColumns="false" OnItemCreated="radListComments_ItemCreated"
            OnUpdateCommand="radListComments_UpdateCommand" OnInsertCommand="radListComments_InsertCommand"
            OnNeedDataSource="radListComments_NeedDataSource" ClientSettings-ClientEvents-OnTreeListCreated="createPrettyCommentsView"
            AllowRecursiveDelete="true" ondeletecommand="radListComments_DeleteCommand" onitemdatabound="radListComments_ItemDataBound">
            <EditFormSettings EditFormType="Template" />
                <telerik:TreeListTemplateColumn HeaderStyle-Width="75%">
                        <asp:LinkButton ID="LinkButton1" ToolTip="New comment thread" ForeColor="Blue" runat="server" CommandName="InitInsert"><img src="" alt="" style="display:inline; line-height:17px; vertical-align:middle; margin-bottom:2px;" /></asp:LinkButton> &nbsp;&nbsp&nbsp; <asp:Literal ID="Literal2" runat="server" Text="Text" />
      <div style="height:20px">Customize for your needs</div>
                    <HeaderTemplate><asp:Literal ID="ltrCol2" runat="server" Text="Options" /></HeaderTemplate>
                        <asp:LinkButton ID="LinkButton1" ToolTip="Reply" ForeColor="Blue" runat="server" CommandName="InitInsert" CommandArgument='<%# Eval("ID_HERE" %>'>
                            <img src="" alt="" style="display:inline; line-height:17px; vertical-align:middle; margin-top:3px;" />
                        <asp:LinkButton ID="EditButton" ToolTip="Edit" ForeColor="Blue" runat="server" CommandName="Edit">
                            <img src="" alt="" style="display:inline; line-height:17px; vertical-align:middle; margin-top:3px;" />
                        <asp:LinkButton ID="DeleteButton" ToolTip="Delete" ForeColor="Blue" runat="server" CommandName="Delete">
                            <img src="" alt="" style="display:inline; line-height:17px; vertical-align:middle; margin-top:3px;" />
            <EditFormSettings EditFormType="Template">
                   Removed as not relevant to topic

You will need to adjust it for your needs, as you can see it required also event handlers to exist in code behind, but will take a look only at some of those:


make you handler look like that:

protected void radListComments_ItemCreated(object sender, TreeListItemCreatedEventArgs e)
            if (e.Item is TreeListDataItem)
                Control expandButton = e.Item.FindControl("ExpandCollapseButton");
                if (expandButton != null)
                    expandButton.Visible = false;

this will remove expand/collapse feature of tree items.

Next add you private fields to you page/control and handle:

private int _radTreeListLastLevelHelper;
private bool _isRadTreeListItemBgColorAlternative;

protected void radListComments_ItemDataBound(object sender, TreeListItemDataBoundEventArgs e)

       if(e.Item.ItemType == TreeListItemType.Item || e.Item.ItemType == TreeListItemType.AlternatingItem) 
               var di = (TreeListDataItem)e.Item;
               // add required attributes for js script
                  _radTreeListLastLevelHelper = HelperMethods.AddAdditionalAttribUsedInUIPrettifierJSScript(di, _radTreeListLastLevelHelper);

               // set bg color
           _isRadTreeListItemBgColorAlternative = HelperMethods.SetCommentItemBgColor(di, _isRadTreeListItemBgColorAlternative);

Static methods are defined as:

public static int AddAdditionalAttribUsedInUIPrettifierJSScript(TreeListDataItem di, int radTreeViewLastLevelHelperVariable)
 // skip first root element
 if (di.DataItemIndex == 0)
  return 0;
 if (radTreeViewLastLevelHelperVariable >= di.HierarchyIndex.NestedLevel)
  di.Attributes.Add("shouldBeSeparated", "20px");
  di.Attributes.Add("shouldBeSeparated", "10px");

 if (di.HierarchyIndex.NestedLevel == 0)
  di.Attributes.Add("shouldBeSeparated", "45px");

 return di.HierarchyIndex.NestedLevel;

public static bool SetCommentItemBgColor(TreeListDataItem di, bool isAlt)
 if (di.HierarchyIndex.NestedLevel == 0)
  isAlt = !isAlt;

  di.BackColor = isAlt ? Color.GhostWhite : Color.WhiteSmoke;

 return isAlt;

Former method adds additional attributes and specify margin depending on the item level. So root items will have 45px between, child of a parent - 10px and when depth level is decreasing use 20px

Latter mathod sets colors of each comment thread (starting from root), so one comment thread will have GhostWhite color and another WhiteSmoke (similar to item and alt item coloring).

Next we need JS method to run on the tree html elements, from markup of RadTreeList you see ClientSettings-ClientEvents-OnTreeListCreated="createPrettyCommentsView":

function is:

function createPrettyCommentsView(sender) {
    var commentsToAdjust = $("#" + sender.get_id() + " tr[shouldBeSeparated]");

    if (commentsToAdjust.length > 0) {

        for (var i = 0; i < commentsToAdjust.length; i++) {
            var separator = $(commentsToAdjust[i]).clone();
            separator.children().html("").css("height", $(commentsToAdjust[i]).attr("shouldBeSeparated"));

            separator.children(":regex(class, .rtlL\\d+)").removeClass().addClass("rtlL rtlL0");

            $("#" + $(commentsToAdjust[i]).attr("id")).prev().children(".rtlCF, .rtlCL").filter(function (index) {
                return $(this).css("border-bottom-width") == "0px";
            }).css("border-bottom-width", "1px");

            $("#" + $(commentsToAdjust[i]).attr("id")).children(".rtlCF, .rtlCL").filter(function (index) {
                return $(this).css("border-top-width") == "0px";
            }).css("border-top-width", "1px");

            $("#" + $(commentsToAdjust[i]).attr("id")).next().children(".rtlCF, .rtlCL").filter(function (index) {
                return $(this).css("border-top-width") == "0px";
            }).css("border-top-width", "1px");

            $("<tr>" + separator.html() + "</tr>").insertBefore(commentsToAdjust[i]);

yeah, might be slightly not optimal, was hacked fast, but does what's needed. And yes, you will need jQuery and one adjustment to jQuery:

/* */
jQuery.expr[':'].regex = function (elem, index, match) {
    var matchParams = match[3].split(','),
        validLabels = /^(data|css):/,
        attr = {
            method: matchParams[0].match(validLabels) ?
                        matchParams[0].split(':')[0] : 'attr',
            property: matchParams.shift().replace(validLabels, '')
        regexFlags = 'ig',
        regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g, ''), regexFlags);
    return regex.test(jQuery(elem)[attr.method](;

snippet above will allow regex based selectors to be used.

Finally to expand all items handle OnPreRender in your page/control:

protected override void OnPreRender(EventArgs e)

That should do it! Hopefully while cleaning for post I didn't break/skipped too much relevant stuff :)))

Weird behavior when debugging ASP.NET Web application: cookie expires (1/1/0001 12:00AM) by itself on next breakpoint hit.

I'm working on ajaxified (Telerik AJAX Manager) ASP.NET application using Visual Studio 2010 (runs with admin privileges) and IIS 7.5. Basically, everything on the page is inside update panels. As for cookies I have custom encrypted "settings" cookie which is added to Response if it's not there on session start. Application runs smoothly, problem was arising when I started the debugging it:


no breakpoints set, F5 - application has started in debug mode, browser window loaded. I login to site, click on controls, all is fine. Next I set *any* breakpoint somewhere in code, break on it then let it continue running, but once I break again (immediately after first break) and check cookie: it has expired date 1/1/0001 12:00AM and no data in value property. I was storing current language there, which was used inside Page's InitializeCulture event and obviously exception was being raised. I spent several hours trying deleting browser cache, temporary ASP.NET files etc, nothing seemed to work.

Same application has been tested on exactly same environment on another PC and no problems with debugging there.

After all I've found the solution: visual studio generates for every solution additional .suo file where additional settings are stored, like UI state, breakpoints info, etc, so I deleted it and loaded project again, tried debugging - everything is ok now.

Flattening System.Web.UI ControlCollection



Sometimes one may need to get a list of child controls inside specific container and don't care about the underlying hierarchy.


The result is beautifully achieved using this extension method:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;


 public static class ControlCollectionExtensionMethods
        public static IEnumerable<Control> FlattenedList(this ControlCollection controls)
            foreach (Control ctrl in controls)
                  // return parent control
                   yield return ctrl;

                  // and dive into child collection
                   foreach (Control child in ctrl.Controls.FlattenedList())
                         yield return child;


P.S.: don't forget about namespaces when using it in your code, if above class is wrapped into namespace, for example: Sample, the source code file with calling code must explicitly reference it: using Sample;

Posted: May 12 2010, 07:24 PM by evovision | with 7 comment(s)
Filed under: , ,
Customizing the processing of ListItems for asp:RadioButtonList with "Flow" layout and "Horizontal" direction


recently I was asked to add an ability to pad specific elements from each other to a certain distance in RadioButtonList control. Not quite common everyday task I would say :)


Ok, let's get started!



ASP.NET Page having RadioButtonList control with RepeatLayout="Flow" RepeatDirection="Horizontal" properties set.



The underlying data was coming from another source, so the only fast way to add meta information about padding was the text value itself (yes, not very optimal solution):

Id = 1, Name = "This is first element" and for padding we agreed to use <space/> meta tag: Id = 2, Name = "<space padcount="30px"/>This is second padded element"


To handle items rendering in RadioButtonList control I've created custom class and subclassed from it:


 public class CustomRadioButtonList : RadioButtonList
        private Action<ListItem, HtmlTextWriter> _preProcess;

        protected override void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
            if (_preProcess != null)
                _preProcess(this.Items[repeatIndex], writer);

            base.RenderItem(itemType, repeatIndex, repeatInfo, writer);

        public void SetPrePrenderItemFunction(Action<ListItem, HtmlTextWriter> func)
            _preProcess = func;


It is pretty straightforward approach, the key is to override RenderItem method. Class has SetPrePrenderItemFunction method which is used to pass custom processing function that takes 2 parameters: ListItem and HtmlTextWriter objects.


Now update existing RadioButtonList control in Default.aspx:

add this to beginning of the page:


<%@ Register Namespace="Sample.Controls" TagPrefix="uc1" %>


and update the control to:


<uc1:CustomRadioButtonList ID="customRbl" runat="server" DataValueField="Id" DataTextField="Name"
            RepeatLayout="Flow" RepeatDirection="Horizontal">


Now, from codebehind of the page:


Add regular expression that will be used for parsing:


private Regex _regex = new Regex(@"(?:[<]space padcount\s*?=\s*?(?:'|"")(?<padcount>\d+)(?:(?:\s+)?px)?(?:'|"")\s*?/>)(?<content>.*)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);


and finally setup the processing function in Page_Load:


protected void Page_Load(object sender, EventArgs e)
        customRbl.DataSource = DataObjects;

        customRbl.SetPrePrenderItemFunction((listItem, writer) =>
            Match match = _regex.Match(listItem.Text);
            if (match.Success)
                writer.Write(string.Format(@"<span style=""padding-left:{0}"">Extreme values: </span>", match.Groups["padcount"].Value + "px"));

                // if you need to pad listitem use code below
                //x.Attributes.CssStyle.Add("padding-left", match.Groups["padcount"].Value + "px");

                // remove meta tag from text
                listItem.Text = match.Groups["content"].Value;



That's it! :)


Run the attached sample application:



P.S.: of course several other approaches could have been used for that purpose including events and the functionality for processing could also be embedded inside control itself.

Current solution suits slightly better due some other reasons for situation where it was used, in your case consider this as a kick start for your own implementation :)


Source application:

Visual Studio 2008 and .NET Framework 3.5 Training Kit
Visual Studio 2008 and .NET Framework 3.5 Training Kit containing Labs, Demos and PPTs that was developed by the Developer and Platform Evangelism Group is available for download here:

Brief Overview

The Visual Studio 2008 and .NET Framework 3.5 Training Kit includes presentations, hands-on labs, and demos. This content is designed to help you learn how to utilize the Visual Studio 2008 features and a variety of framework technologies including: LINQ, C# 3.0, Visual Basic 9, WCF, WF, WPF, ASP.NET AJAX, VSTO, CardSpace, SilverLight, Mobile and Application Lifecycle Management.
Implementing a multisort column in GridView

Article topic came from my current project, I needed to implement a multisort column in GridView so that end users would have more convenient sorting.

Please read the article here: 

Posted: Jan 09 2008, 10:00 PM by evovision | with 2 comment(s)
Filed under: , ,
Welcome onboard

Thank you for visiting my blog!

One day, late night I've been browsing around the web, searching for some interesting articles to read and again that old idea came up - start running own blog, yeah, sounds great but lot's of thing to do, lack of time, study, etc and as always I've almost suppressed that idea, but... it came up again and again. Hm, supposed to be like somekind of a sign I thought, ok, I decided to start running a blog on one of my fav sites and with a help of Joe Stagner I'm here today with you.

So, enjoy your stay and let's get started ;-)


Posted: Jan 09 2008, 09:46 PM by evovision | with 8 comment(s)
Filed under: , ,
More Posts