In one my previous post I wrote how to use Telerik Rad Editor Lite for Firefox (and other than IE browsers). Here we will extend the control which we created in order to use it in all sites without additional actions from your side. In order to use Telerik Rad Editor you need to activate 2 features:
- Use RadEditor to edit List Items (located in RadEditorFeature)
- Use RadEditor to edit List Items in Internet Explorer as well (located in RadEditorFeatureIE)
First feature during activation copies new rendering template for RichTextField with Telerik control which replaces default Sharepoint editor for html fields (copying is done in feature receiver). Second feature doesn’t have feature receiver – instead it has activation dependency on 1st feature and used as a flag (see below).
Control checks that these features are activated in the OnLoad() method:
If we want to use Telerik editor on all sites without activating the features, we need to override ShowEditorOnPage() method and always return true.
In the previous post we already created custom control which inherits RadHtmlListField. Now we need extend it – override OnLoad() method. As it access private variables and methods we need to reuse reflection in order to simulate work of the RadHtmlListField. Mostly all places where it access private variables can be solved with basic reflection, but not all. See that it calls base.OnLoad() method (line 5), i.e. it calls OnLoad() method of the base class MOSSRadEditor. As we have our own class which inherits RadHtmlListField, then inheritance chain looks like this:
AllBrowsersHtmlListField –> RadHtmlListField –> MOSSRadEditor
In our AllBrowsersHtmlListField we want to call MOSSRadEditor.OnLoad(), but not RadHtmlListField.OnLoad() – it means that we can’t call base.OnLoad(). I.e. we need to skip one tier in the inheritance chain and call virtual method OnLoad(), but not from base class, but from base of base class. And this is not trivial task because it means that we need to avoid the rules of the underlying programming language.
Investigation of this problem showed that problem is really not simple. But in this forum thread I found interesting mention that DynamicMethod can be used for this. The idea is that we will build new method in runtime using IL instructions and then call it. In our case it will look like this:
At first we get a reference to the MOSSRadEditor.OnLoad() method (lines 3-6). Then we create new DynamicMethod (BaseBaseOnLoad) and specify in parameters type of AllBrowsersHtmlListField (type of object which is used for calling) and EventArgs which is passed to the OnLoad() method. Then using IL generator we create method’s body (lines 10-13). Note that on line 9 we construct call to the method which actually makes trick – because this call will go to the MOSSRadEditor type. Then we create delegate and call it with parameters which we specified earlier (lines 15-17).
It was complex part. The rest of things can be done with basic reflection. We will need extended ReflectionHelper class:
With this helper class we can change all calls to the private members and perform them by reflection. Final solution will look like this:
It works in FF (and you can extend it also for other browsers) and doesn’t require features activation. Note that it will be used on all sites in your farm because rendering template is used globally by Sharepoint. However you can easily to change this behavior – check url of the current web application in the NewShowEditorOnPage() method and decide whether or not you need to use Telerik control.
This post showed that how knowledge of advanced language features may help in applied Sharepoint development. Hope it will help you in your work.