Asked by:
Webparts

Question
-
User-1390805452 posted
A suggestion for the next release.
It would be nice to have all the webpart, webpartzone, catalog, editor etc. rendered with friendly CSS as well.
Thanks and keep up the good work.
MickThursday, May 4, 2006 12:11 PM
All replies
-
User-1660928712 posted
I really second thatThursday, May 4, 2006 5:18 PM -
User-383693083 posted
Hi,
it will be really great to have a clear WebParts!!! Please, think about it...
Thank youFriday, June 9, 2006 3:29 PM -
User-534056067 posted
It's already on the radar, so to speak, though I don't have any code to share yet.
As always, this kind of clear guidance is much appreciated.
Friday, June 9, 2006 4:02 PM -
User-534056067 posted
Would anyone like to share their "vision" of the markup and CSS they'd like to see for web parts and their related controls? I'd love to get a better sense of what people see as the most egregious problems with the markup rendered today. And, by contrast, what ought to be rendered instead.
Friday, June 9, 2006 4:16 PM -
User-383693083 posted
Would anyone like to share their "vision" of the markup and CSS they'd like to see for web parts and their related controls? I'd love to get a better sense of what people see as the most egregious problems with the markup rendered today. And, by contrast, what ought to be rendered instead.
Hi,
okey, i'll try to make a simple "vision", how can WebParts look like without tables. Where can i send it to you than?Saturday, June 10, 2006 10:03 AM -
User-2097903674 posted
My main objection to the current web part rendering is the use of tables.
Has there been any further progress on this?
A good first step would be to at least replace the table mark-up from the read-only/view mode which site visitors will see, and then worry about the editing modes later on. This would at least mean that members of the public visiting a site wouldn't see something riddled with tables.
I'm willing to give this a go, but have a feeling that only someone with access to the Microsoft source code would be able to do this reliably?
Any help/ideas would be much appreciated,
Tom
Wednesday, January 17, 2007 4:53 AM -
User-2097903674 posted
I've had a go based on Russ Helfand's excellent post.
WebPartZoneAdapter.cs
using System;
Default.aspx
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
namespace CSSFriendly
{
public class WebPartZoneAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
protected override void RenderBeginTag(HtmlTextWriter writer)
{
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
base.RenderBeginTag(hw);
hw.Flush();
hw.Close();
string origTag = sw.ToString();
string newTag = origTag;
//string newTag = Regex.Replace(origTag, "\\s*style=[\"'][^\"']*[\"']", "", RegexOptions.Multiline | RegexOptions.IgnoreCase); writer.Write(newTag); } protected override void RenderEndTag(HtmlTextWriter writer)
{
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
base.RenderEndTag(hw);
hw.Flush();
hw.Close();
string origTag = sw.ToString();
string newTag = origTag;
//string newTag = Regex.Replace(origTag, "\\s*style=[\"'][^\"']*[\"']", "", RegexOptions.Multiline | RegexOptions.IgnoreCase); writer.Write(newTag); } protected override void RenderContents(HtmlTextWriter writer)
{
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
base.RenderContents(hw);
hw.Flush();
hw.Close();
string origTag = sw.ToString();
string newTag = origTag;
//string newTag = Regex.Replace(origTag, "\\s*style=[\"'][^\"']*[\"']", "", RegexOptions.Multiline | RegexOptions.IgnoreCase); writer.Write(newTag); } } }<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>ASP.NET 2.0 CSS Friendly Control Adapters 1.0</title>
</head>
<body>
<asp:WebPartManager ID="WebPartManager1" runat="server">
</asp:WebPartManager>
<asp:WebPartZone ID="WebPartZone1" runat="server">
<ZoneTemplate>
Hello
</ZoneTemplate>
</asp:WebPartZone>
</body>
</html>CSSFriendlyAdapters.browser
<adapter controlType="System.Web.UI.WebControls.WebParts.WebPartZone"
adapterType="CSSFriendly.WebPartZoneAdapter" />But the base.RenderEndTag(hw); is causing an error: "A PopEndTag was called without a corresponding PushEndTag."
Wednesday, January 17, 2007 6:45 AM -
User-534056067 posted
Cool stuff. Let me see if I can help you overcome the error you reported. Consider going with something like this for the adapter code. I'm not 100% it will work for your purposes but my testing seems to indicate that it fix the problem...
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
namespace CSSFriendly
{
public class WebPartZoneAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
protected StringWriter sw = null;
protected HtmlTextWriter hw = null;public WebPartZoneAdapter()
{
sw = new StringWriter();
hw = new HtmlTextWriter(sw);
}protected override void RenderBeginTag(HtmlTextWriter writer)
{
base.RenderBeginTag(hw);
hw.Flush();
string origTag = sw.ToString();
string newTag = origTag;
//string newTag = Regex.Replace(origTag, "\\s*style=[\"'][^\"']*[\"']", "", RegexOptions.Multiline | RegexOptions.IgnoreCase);
writer.Write(newTag);
}
protected override void RenderEndTag(HtmlTextWriter writer)
{
base.RenderEndTag(hw);
hw.Flush();
hw.Close();
string origTag = sw.ToString();
string newTag = origTag;
//string newTag = Regex.Replace(origTag, "\\s*style=[\"'][^\"']*[\"']", "", RegexOptions.Multiline | RegexOptions.IgnoreCase);
writer.Write(newTag);
}
protected override void RenderContents(HtmlTextWriter writer)
{
base.RenderContents(hw);
hw.Flush();
string origTag = sw.ToString();
string newTag = origTag;
//string newTag = Regex.Replace(origTag, "\\s*style=[\"'][^\"']*[\"']", "", RegexOptions.Multiline | RegexOptions.IgnoreCase);
writer.Write(newTag);
}
}
}
Thursday, January 18, 2007 2:22 PM -
User-2097903674 posted
Thanks Russ, that gets rid of the error.
I've managed to use the Regex to change the rendered output, now I just need to find time to go through it more thoroughly and to check it doesn't break any functionality.
I'll post code here as soon as I've made some progress.
Monday, January 22, 2007 4:24 AM -
User-384517966 posted
Not really a vision, just some things I was thinking about...
- More so called unobtrusive javascript.
- All controls covered (CheckBoxList is a table!)
- Somehow offer a better package with all stuff in a DLL, including javascript (more like the recently released Ajax Extensions)
- Is the GAC the right place for it?
- Is it possible to have everything (including javascript and CSS) in one dll, but still let us style the controls?
- Move the project to Codeplex (it did the Ajax Control Toolkit good)
- A weblog on the CSSAdapters site
Sunday, January 28, 2007 4:20 PM -
User-384517966 posted
Oh and one more thing:
to prevent a battle of the window.onload event handlers either you guys should add your IE6 specific hover script to already existing eventhandlers, or give instructions to us how to do that, because if the cssfriendly scripts execute after mine, they will override any onload events I had set.
Thanks!
PS: another reason to look into the Ajax javascript classes, they offer this functionality.
Sunday, January 28, 2007 4:43 PM -
User955313812 posted
Hello Folks,
Thanks for the great ideas on creating WAI compliant pages. I've just had to create a MOSS2007 Site which had to be AA compliant and it proved most exhausting. here is my version of the webpartzoneadapter that worked for me. Please note: this adapter is only used for the output of the contents of the webpartzone and does not support interactions. But using Regex I strip out all the nasty tables that are not needed for output purposes.
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
namespace CSSFriendly
{
public class WebPartZoneAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
protected StringWriter sw = null;
protected HtmlTextWriter hw = null;public WebPartZoneAdapter()
{
sw = new StringWriter();
hw = new HtmlTextWriter(sw);
}protected override void RenderBeginTag(HtmlTextWriter writer)
{//don't render the table tag
}
protected override void RenderEndTag(HtmlTextWriter writer)
{//don't render the table end tag
}
protected override void RenderContents(HtmlTextWriter writer)
{
base.RenderContents(hw);
string origTag = sw.ToString();
string html = Regex.Replace(origTag , @"<[/]?(table|tr|td|[ovwxp]:\w+)[^>]*?>", "", RegexOptions.IgnoreCase);
writer.Write(html);
writer.Write(Control.Controls.Count);
}
}
}
Tuesday, March 6, 2007 8:36 PM -
User2025654956 posted
I'm having a bit of a problem with Russ' example. When I do the example above it prints out two of the same web part. For example, if I throw in a calendar into the web part zone, it will print two calendar web parts on the page. It looks like it's adding in an extra table and such and I have no idea why. I'm simply printing out exactly what the base class renders so I have no clue why this is happening. When I remove the adapter it only prints 1 calendar.
Does anybody have a similar problem or know a solution?
Thanks!
Shawn
Wednesday, April 4, 2007 12:07 AM -
User-2097903674 posted
I've created a complete example which almost works, but still isn't quite right. I need to find a way of stopping the rendering being overridden when in Design view, but I'm not sure how.
http://www.tjrobinson.net/temp/CssFriendlyWebPartZone.zip
Thursday, April 26, 2007 10:20 AM -
User1088575861 posted
Hi Guys,
Is it possible to do this using the Web.config file rather than the .browser ?
Friday, June 29, 2007 7:04 AM -
User-534056067 posted
No. That's the simple answer.
However, I've provided guidance in the past about how to programmatically manipulate any page's list of adapters. Beware, though, that you can tweak that list for the page only during very limited portions of the page's life cycle (e.g., during only a limited number of page events). First, read this, http://forums.asp.net/t/1105715.aspx. Second, consider how you might modify the code to serve your purposes. You've asked if you can avoid touching the .browser file in the App_Browsers folder. You've implied that you would prefer to use an alternative approach, like adding something to a web.config in a folder you, presumably, have control over. You can't do that but you could use the approach outlined in the forum posting I referred to in order to add or remove adapters from the set that the current page is about to use, thus effectively accomplishing what a .browser file is meant to do.
Of course you'd need to modify the given code a bit. It's original purpose as written is to disable a bunch of adapters for a page. Instead you might want the initialization code to create adapters and add them to the page's list and then remove those when the page is unloaded. I've never tried that, frankly, but it seems plausible to do.
I'll be very curious to hear what your experience is if you try this approach. Please do write back and good luck to you.
Friday, June 29, 2007 1:10 PM -
User1088575861 posted
Thanks for the help. Your answer helped me convince my seniors that using the .browser file is the best and easiet way. I have now implemented it and it look great (with a little CSS).
Wednesday, July 11, 2007 6:57 AM -
User-577735880 posted
Hi Folks,
I have the all the examples given here regarding tableless webparts, but ended in disappointment. Even though the code given by alexdean is working, it has its own drawbacks say, if we try to add a datagrid or gridview etc which generates tables are also removed when added as a webpart. here i've given a simple solution for this. i hope it might work properly for all. The rest of the things should be done via CSS.
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Collections;
namespace CSSFriendly
{
public class WebPartZoneAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
private WebControlAdapterExtender _extender = null;
#region Extender
private WebControlAdapterExtender Extender
{
get
{
if (((_extender == null) && (Control != null)) ||
((_extender != null) && (Control != _extender.AdaptedControl)))
{
_extender = new WebControlAdapterExtender(Control);
}
System.Diagnostics.Debug.Assert(_extender != null, "CSS Friendly adapters internal error", "Null extender instance");
return _extender;
}
}
#endregion
/// PROTECTED
#region OnInit
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Extender.AdapterEnabled)
{
// Some Code RegisterScripts etc
}
}
#endregion
#region RenderBeginTag
protected override void RenderBeginTag(HtmlTextWriter writer)
{//don't render the table tag
if (Extender.AdapterEnabled)
{
WebPartZone wp = Control as WebPartZone;
if (wp != null)
{
if(wp.LayoutOrientation==System.Web.UI.WebControls.Orientation.Horizontal)
Extender.RenderBeginTag(writer, "AspNet-WebPartZone-Horizontal");
else if (wp.LayoutOrientation == System.Web.UI.WebControls.Orientation.Vertical)
Extender.RenderBeginTag(writer, "AspNet-WebPartZone-Vertical");
}
}
else
{
base.RenderBeginTag(writer);
}
}
#endregion
#region RenderEndTag
protected override void RenderEndTag(HtmlTextWriter writer)
{
if (Extender.AdapterEnabled)
{
Extender.RenderEndTag(writer);
}
else
{
base.RenderEndTag(writer);
}
}
#endregion
#region RenderContents
protected override void RenderContents(HtmlTextWriter writer)
{
if (Extender.AdapterEnabled)
{
WebPartZone wpz = Control as WebPartZone;
if (wpz != null)
{
writer.Indent++;
writer.WriteLine();
writer.WriteBeginTag("div");
writer.WriteAttribute("id", wpz.ID);
if (!String.IsNullOrEmpty(wpz.CssClass))
{
writer.WriteAttribute("class", wpz.CssClass);
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
WebPartCollection wpColl = null;
///////////////////// GENERATE WEBPARTS /////////////////////////////
if (wpz.WebParts.Count > 0)
{
wpColl = new WebPartCollection(wpz.WebParts);
foreach (WebPart wp in wpColl)
{
writer.WriteLine();
writer.WriteBeginTag("span");
if (!String.IsNullOrEmpty(wpz.CssClass))
{
writer.WriteAttribute("class", "WebPart");
}
writer.Write(HtmlTextWriter.TagRightChar);
wp.RenderControl(writer);
writer.WriteEndTag("span");
writer.Indent++;
}
writer.WriteEndTag("div");
}
writer.Indent--;
writer.WriteLine();
}
}
else
{
base.RenderContents(writer);
}
}
#endregion
}
}
i will appretiate any further improvements on this.
Best Regards,
Karthik.
Monday, September 17, 2007 8:37 AM -
User1462465203 posted
Hi you all,
I have read all of your posts and I am very impressed of your work. I am doing an e-learning asp.net application and I want to meet WAI-AA requirements. One of them is that the website must work without javascript. I have found out how to minimize a webpart without javascript using a submit button, but I can't render this button in the webpart's header. When I render the button in the webpart's header, the server did not notice the click.The code that minimizes the webpart
void boton_Click(object sender, EventArgs e) { Button boton = (Button)sender; ((TemplatedWebPartZone)Zone).PublicRaisePostBackEvent("minimize:" + boton.CommandArgument); if (true) throw new Exception("we"); }
boton.CommandArgument is the webpart's ID
I create the buttons in the render method of the webpartzone. Do I have to add them to a Control collection? What I am doing wrong?
Thanks for your answers and sorry for my bad English.
Friday, December 28, 2007 7:11 PM -
User1893902719 posted
Hi Russ,
Appologies if this is a bit out of context (nothing to do with webparts), but I tried the above adapter on a "System.Web.UI.WebControls.Calendar"
and it rendered like this:
<table id="ctl00_Main_SingleDayInput" class="calendarControl">
</table>
got any tips? :-)
Cheers.
Murray
Sunday, February 10, 2008 11:35 PM