Thursday, August 17, 2006
Disable the edit verb on a web part: practically impossible
This thread on ASP.NET forums called my attention to a fact about ASP.NET 2 web parts that I had never noticed before. When you set AllowClose on a web part to False, the web part infrastructure will hide the Close verb from the user. The setting will not only prevent the action of Closing with an exception, but will also hide forbidden options in the UI.
However, when you set AllowEdit to False, the Edit verb does not disappear; when you select Edit, the EditorZone will not display any tool part, but you can still switch to edit mode. Why would that be?
I checked the code with Reflector and indeed, in the WebPartChrome.ShouldRenderVerb method, the logic seems to make and exception for the Edit verb: the right display mode is checked, but no check for the AllowEdit property on the web part. Also, the designers of the framework seem to have intentionally made fixing this very hard: you can create a custom subclass of WebPartChrome, but
- ShouldRender is private, so cannot be overridden
- FilterWebPartVerbs, which uses ShouldRender is virtual, but if you override it, you cannot add or remove verbs from the WebPartVerbCollection the base implementation returns, because it has no Remove method and Add is marked internal
- You cannot subclass from WebPartVerbCollection to add these features, as it is sealed
- You cannot use the WebPartVerbCollection(ICollection) constructor, because the verbs that are created by the WebPartZone all have ID "". The copy constructor will refuse to create a collection with duplicate IDs (except by usings the internal Add method, which is fine with duplicate IDs)
It escapes me why it would be so bad to have the opportunity to remove verbs that were added by the base implementation and I am still wondering why we should not hide the Edit verb from users when editing is not allowed anyway.
It all looks a bit sloppy to me.
Labels: aspnet_webparts
{
protected override WebPartChrome CreateWebPartChrome()
{
return new MyChrome(this, this.WebPartManager);
}
}
public class MyChrome : WebPartChrome
{
public MyChrome(WebPartZoneBase myZone, WebPartManager WPM)
: base(myZone, WPM)
{
}
protected override WebPartVerbCollection FilterWebPartVerbs(WebPartVerbCollection verbs, WebPart webPart)
{
WebPartVerbCollection WPC = base.FilterWebPartVerbs(verbs, webPart);
foreach (WebPartVerb verb in WPC)
{
if (verb == this.Zone.EditVerb)
{
verb.Enabled = webPart.AllowEdit;
}
}
return WPC;
}
}
I guess its not completely impossible to disable edit verb. You can create a ReadOnly flag in custom webpart implementation and based on this flag you can show/hide edit verb. Here's a sample code to disable/remove Edit, Minimize and Close verb from a webpart:
public class MyWebPart : WebPart {
...
private WebPartVerbCollection _verbs;
private bool _booReadOnly =
false;
// set this property to true for webparts which needs to be ReadOnly
public bool ReadOnly {
get {
return _booReadOnly;
}
set {
_booReadOnly = value;
if (value) {
this.AllowEdit = false;
this.AllowClose = false;
this.AllowMinimize = false;
this.AllowZoneChange = false;
this.ChromeType = PartChromeType.None;
}
}
}
...
public override WebPartVerbCollection Verbs {
get {
if (this._verbs == null && !this.ReadOnly) {
ArrayList verbs = new ArrayList();
MyEditWebPartVerb editVerb = new MyEditWebPartVerb(OnEditWebPart);
verbs.Add(editVerb);
this._verbs = new WebPartVerbCollection(verbs);
}
return this._verbs;
}
}
void OnEditWebPart(object sender, WebPartEventArgs e) {
MyWebPartZone zone = e.WebPart.Zone as MyWebPartZone;
if (zone != null) {
zone.OnEditWebPart(e.WebPart);
}
}
}
// Create your custom Edit verb
public class MyEditWebPartVerb : WebPartVerb {
private String _strEditWebPartImageUrl =
"~/img/EditVerb.GIF";
internal MyEditWebPartVerb (WebPartEventHandler serverClickHandler)
:
base("EditVerb", serverClickHandler) { }
internal MyEditWebPartVerb (WebPartEventHandler serverClickHandler, String clientClickHandler)
:
base("EditVerb", serverClickHandler, clientClickHandler) { }
public override string Text {
get { return "Edit"; }
set { base.Text = value; }
}
public override string Description {
get {
return "Edit this web part control.";
}
set { base.Description = value; }
}
public override bool Enabled {
get { return base.Enabled; }
set { base.Enabled = value; }
}
public override string ImageUrl {
get { return _strEditWebPartImageUrl; }
set { _strEditWebPartImageUrl = value; }
}
}
public class MyWebPartZone : Microsoft.Web.UI.Controls.WebParts.WebPartZone {
...
public void OnEditWebPart(WebPart webpart) {
base.EditWebPart(webpart);
}
}
Hope the code makes sense.
Cheers,
Haresh
Links to this post:
<< Home



