using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Text.RegularExpressions;//设置该组件的标记前缀
[assembly:TagPrefix("UserControls.HtmlEdit", "HtmlEditV1")]
namespace UserControls.HtmlEdit
{
//添加类声明 
[
DefaultProperty("Text"),
ValidationProperty("Text"),
ToolboxData("<{0}:HtmlEdit runat=server></{0}:HtmlEdit>"),
ParseChildren(false),
Designer("UserControls.HtmlEdit.UltraTextBoxV1Designer")
]
//public class HtmlEdit: System.Web.UI.Control, IPostBackDataHandler,INamingContainer
public class HtmlEdit: System.Web.UI.Control, IPostBackDataHandler,INamingContainer
{
private static readonly object ValueChangedEvent = new object();
//声明一个代理用于处理值被改变的事件,当组件的值更改时发生ValueChanged事件 
public event EventHandler ValueChanged
{
add
{
Events.AddHandler(ValueChangedEvent, value);
}
remove
{
Events.RemoveHandler(ValueChangedEvent, value) ;
}
}
//触发值被改变事件的方法
protected virtual void OnValueChanged(EventArgs e)
{
if( Events != null )
{
EventHandler oEventHandler = ( EventHandler )Events[ValueChangedEvent] ;
if (oEventHandler != null) oEventHandler(this, e);
}
}
//处理回发数据 
bool IPostBackDataHandler.LoadPostData( string postDataKey, System.Collections.Specialized.NameValueCollection postCollection )
{ if ( postCollection[postDataKey] != Text || postCollection[postDataKey+"BgSound"] != TextBgSound )
{
Text = postCollection[postDataKey];
TextBgSound = postCollection[postDataKey+ "BgSound"];
return true;
}
return false;
}
//告诉应用程序该组件的状态已更改 
void IPostBackDataHandler.RaisePostDataChangedEvent()
{
OnValueChanged( EventArgs.Empty );
}
//-------------------------------------------------
// Defines the Click event.
public event EventHandler Click;
      
// Invokes delegates registered with the Click event.
protected virtual void OnClick(EventArgs e) 
{     
if (Click != null) 
{
//Click(this, e);
EventHandler oEventHandler = ( EventHandler )Events[Click] ;
if (oEventHandler != null) oEventHandler(this, e);
}  
}      
// Method of IPostBackEventHandler that raises change events.
public void RaisePostBackEvent(string eventArgument)
{     
OnClick(EventArgs.Empty);
}
//------------------------------------------------- //我们对一个编辑器主要需要实现下面4个属性,Text,Width,Height,BasePath。 //Text属性:(从编辑器得到值和把值赋给编辑器)
[Bindable(true),DefaultValue("")] 
public string Text
{
get 
{
object o = ViewState["Text"];
return ( o == null ) ? String.Empty : ( string )o;
}
set
{
ViewState["Text"] = value;
}
}
//TextBgSound属性:(从编辑器得到值和把值赋给编辑器)
[Bindable(true),DefaultValue("")] 
public string TextBgSound
{
get 
{
object o = ViewState["TextBgSound"];
return ( o == null ) ? String.Empty : ( string )o;
}
set
{
ViewState["TextBgSound"] = value;
}
} //Width属性:(编辑器的宽)
[Bindable(true),Category("Appearence"),DefaultValue("100%")] 
public Unit Width
{
get 
{
object o = ViewState["Width"];
return ( o == null ) ? Unit.Parse( "100%" ) : ( Unit )o ;
}
set

ViewState["Width"] = value ;
}
} //Width属性:(编辑器的宽)
[Bindable(true),Category("Appearence"),DefaultValue("100%")] 
public Unit WidthBgsound
{
get 
{
object o = ViewState["WidthBgsound"];
return ( o == null ) ? Unit.Parse( "100%" ) : ( Unit )o ;
}
set

ViewState["WidthBgsound"] = value ;
}
}
//Height属性:(编辑器的高)
[Bindable(true),Category("Appearence"),DefaultValue("300px")] 
public Unit Height
{
get 
{
object o = ViewState["Height"];
return ( o == null ) ? Unit.Parse( "230px" ) : ( Unit )o ;
}
set
{
ViewState["Height"] = value ;
}
}
//HeightBgsound属性:(编辑器的高)
[Bindable(true),Category("Appearence"),DefaultValue("100px")] 
public Unit HeightBgsound
{
get 
{
object o = ViewState["HeightBgsound"];
return ( o == null ) ? Unit.Parse( "80px" ) : ( Unit )o ;
}
set
{
ViewState["HeightBgsound"] = value ;
}
} //BasePath属性:(第一步保存的editor.aspx的路径以及以后做的插件的路径)
[Bindable(true),DefaultValue("HtmlEditV1/Plug-Ins/")] 
public string BasePath
{
get 
{
object o = ViewState["BasePath"];
return (o == null) ? "HtmlEditV1/Plug-Ins/" : (string)o+"/";
}
set
{
ViewState["BasePath"] = value;
}
}  //ImagePath属性:(上传的图片及背景图片的目录,它是相对与editor.aspx的路径)
[Bindable(true),DefaultValue("images")] 
public string ImagePath
{
get 
{
object o = ViewState["ImagePath"];
return (o == null) ? "images" : (string)o+"/";
}
set
{
ViewState["ImagePath"] = value;
}
}  //接下来是最重要的怎样把本组件和Editor.aspx结合起来,这里使用的是iframe技术:
//覆盖Render方法,运行时输出:
protected override void Render(HtmlTextWriter output)
{
System.Web.HttpBrowserCapabilities oBrowser = Page.Request.Browser ;
//对应的IE版本必须是5.5或以上的版本 
if (oBrowser.Browser == "IE" && oBrowser.MajorVersion >= 5.5 && oBrowser.Win32)
{
string ddd = "&cif="+ImagePath+ "&rif="+ImagePath;
string sLink = BasePath + "Editor.aspx?FieldName=" + UniqueID + ddd;
string sLinkBgsound = BasePath + "EditorBgsound.aspx?FieldName=" + UniqueID+ddd;
//存储编辑器的值 
output.Write("<INPUT type=\"hidden\" id=\"{0}\" name=\"{0}\" value=\"{1}\" >",UniqueID,System.Web.HttpUtility.HtmlEncode(Text) ) ;
string bbb = "{5}.HtmlEdit.document.body.innerHTML = document.getElementById(\'{4}\').value";
output.Write("<IFRAME id=\"{5}\" src=\"{0}\" width=\"{1}\" height=\"{2}\" frameborder=\"no\" scrolling=\"yes\" onload=\""+bbb+"\" onblur=\"document.getElementById(\'{4}\').value = {5}.HtmlEdit.document.body.innerHTML\"></IFRAME>",sLink,Width,Height,Text,UniqueID,ID + "_editor");
//加入背景音乐文件的上传功能.
output.Write("<INPUT type=\"hidden\" id=\"{0}\" name=\"{0}\" value=\"{1}\" >",UniqueID+"BgSound",System.Web.HttpUtility.HtmlEncode(TextBgSound) ) ;

string bbbBgSound = "if ({5}.document.getElementById('txtBgSound').value == '') {5}.document.getElementById('txtBgSound').value = document.getElementById(\'{4}\').value";
output.Write("<IFRAME id=\"{5}\" src=\"{0}\" width=\"{1}\" height=\"{2}\" frameborder=\"yes\" scrolling=\"yes\" onload=\""+bbbBgSound+"\"></IFRAME>",sLinkBgsound,WidthBgsound,HeightBgsound,TextBgSound,UniqueID+"BgSound",ID + "_editorBgsound");

output.Write("<input type =\"submit\" value = \"预览\" id =\"{0}View\" name =\"{0}View\">",UniqueID);
}
}
//接下来给该组件实现一个设计时的界面:
public class UltraTextBoxV1Designer : System.Web.UI.Design.ControlDesigner
{
public UltraTextBoxV1Designer(){}
public override string GetDesignTimeHtml() 
{
HtmlEdit oControl = ( HtmlEdit )Component ;
return String.Format("<TABLE width=\"{0}\" height=\"{1}\" bgcolor=\"#f5f5f5\" bordercolor=\"#c7c7c7\" cellpadding=\"0\" cellspacing=\"0\" border=\"1\"><TR><TD valign=\"middle\" align=\"center\">HtmlEditV1 - <B>{2}</B></TD></TR></TABLE>",oControl.Width,oControl.Height,oControl.ID ) ;
}
}} 

解决方案 »

  1.   

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    namespace UserControlsTest
    {
    /// <summary>
    /// HtmlEditTest 的摘要说明。
    /// </summary>
    public class HtmlEditTest : System.Web.UI.Page
    { protected UserControls.HtmlEdit.HtmlEdit HtmlEdit1;

    private void Page_Load(object sender, System.EventArgs e)
    {
    // 在此处放置用户代码以初始化页面
    } #region Web 窗体设计器生成的代码
    override protected void OnInit(EventArgs e)
    {
    //
    // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
    //
    InitializeComponent();
    base.OnInit(e);
    }

    /// <summary>
    /// 设计器支持所需的方法 - 不要使用代码编辑器修改
    /// 此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {     this.Load += new System.EventHandler(this.Page_Load);
    this.HtmlEdit1.Click += new System.EventHandler(this.HtmlEdit1_Click);
    }
    #endregion private void HtmlEdit1_Click(object sender, System.EventArgs e)
    {
    string strContent = HtmlEdit1.Text.ToString();
    string strBgSound = HtmlEdit1.TextBgSound.ToString();
    Response.Write("<br>view:content "+strContent);
    Response.Write("<br>view:bgSound "+strBgSound);
    }
    }
    }
      

  2.   

    protected virtual void OnClick(EventArgs e) 
    {     
    if (Click != null) 
    {
    //Click(this, e);
    EventHandler oEventHandler = ( EventHandler )Events[Click] ;
    if (oEventHandler != null) oEventHandler(this, e);
    }  
    }
    改成
    protected virtual void OnClick(EventArgs e) 
    {     
    if (Click != null) 
    {
        Click(this, e);
    }  
    }
    不知道C#是否这样,我VB。NET是raiseevent click(me,e)
    就上面的,你去试试吧,恩!
      

  3.   

    你看看运行后的HTML代码是什么,你运行后,查看下原代码是啥看看生成后元代吗是否有错
      

  4.   

    在这里,你好像也没有实现
    IPostBackEventHandler接口啊?public void RaisePostBackEvent(string eventArgument)
    {     
    OnClick(EventArgs.Empty);
    }这里这个就没实现PostBackEventHandler接口啊。
      

  5.   

    public class HtmlEdit: System.Web.UI.Control, IPostBackDataHandler,IPostBackEventHandler,INamingContainer这样。。然后把你原来的public void RaisePostBackEvent(string eventArgument)
    {     
    OnClick(EventArgs.Empty);
    }
    删除掉。然后,你只要把鼠标点到
    public class HtmlEdit: System.Web.UI.Control, IPostBackDataHandler,IPostBackEventHandler,INamingContainer最后面。然后按回车。
    那个接口的方法就回出来了。你再实现它,把OnClick(EventArgs.Empty);
    这句粘贴进去,看看是否可行哦。我也是刚学不久这个自定义控件,呵呵。
      

  6.   

    和还是不行的
    public event EventHandler Click;
          
    // Invokes delegates registered with the Click event.
    protected virtual void OnClick(EventArgs e) 
    {     
    if (Click != null) 
    {
    Click(this, e);
    //EventHandler oEventHandler = ( EventHandler )Events[Click] ;
    //if (oEventHandler != null) oEventHandler(this, e);
    }  
    }
    void IPostBackEventHandler.RaisePostBackEvent ( string eventArgument )
    {
    OnClick ( EventArgs.Empty );
    }
    ----------------------------------客户端预览按钮好象没事件.
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
    <HEAD>
    <title>HtmlEditTest</title>
    <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
    <meta content="C#" name="CODE_LANGUAGE">
    <meta content="JavaScript" name="vs_defaultClientScript">
    <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    </HEAD>
    <body MS_POSITIONING="FlowLayout">
    <form name="Form1" method="post" action="HtmlEditTest.aspx" id="Form1">
    <input type="hidden" name="__VIEWSTATE" value="dDwxOTc5MjM3NDk7Oz687zLvDNMIevxEJoKLsdQCksH3HA==" /> <FONT face="宋体">
    <TABLE id="Table1" cellSpacing="1" cellPadding="1" width="100%" border="1">
    <TR>
    <TD></TD>
    <TD></TD>
    <TD></TD>
    </TR>
    <TR>
    <TD style="HEIGHT: 18px"></TD>
    <TD style="HEIGHT: 18px"><INPUT type="hidden" id="HtmlEdit1" name="HtmlEdit1" value="" ><IFRAME id="HtmlEdit1_editor" src="HtmlEditV1/Plug-Ins/Editor.aspx?FieldName=HtmlEdit1&cif=images&rif=images" width="100%" height="230px" frameborder="no" scrolling="yes" onload="HtmlEdit1_editor.HtmlEdit.document.body.innerHTML = document.getElementById('HtmlEdit1').value" onblur="document.getElementById('HtmlEdit1').value = HtmlEdit1_editor.HtmlEdit.document.body.innerHTML"></IFRAME><INPUT type="hidden" id="HtmlEdit1BgSound" name="HtmlEdit1BgSound" value="" ><IFRAME id="HtmlEdit1_editorBgsound" src="HtmlEditV1/Plug-Ins/EditorBgsound.aspx?FieldName=HtmlEdit1&cif=images&rif=images" width="100%" height="80px" frameborder="yes" scrolling="yes" onload="if (HtmlEdit1_editorBgsound.document.getElementById('txtBgSound').value == '') HtmlEdit1_editorBgsound.document.getElementById('txtBgSound').value = document.getElementById('HtmlEdit1BgSound').value"></IFRAME><input type ="submit" value = "预览" id ="HtmlEdit1View" name ="HtmlEdit1View"></TD>
    <TD style="HEIGHT: 18px"></TD>
    </TR>
    <TR>
    <TD></TD>
    <TD></TD>
    <TD></TD>
    </TR>
    </TABLE>
    </FONT>
    </form>
    </body>
    </HTML>
      

  7.   

    下面是一个例子,里面只有一个HTML按钮,但我的里面的按钮的ID是根据控件的ID组合的,我调试的时候那个按钮的事件还是不触发.
    output.Write("<input type =\"submit\" value = \"预览\" id =\"{0}View\" name =\"{0}View\">",UniqueID);
    ----------------------
    using System;
    using System.Web.UI;
    using System.Collections;
    using System.Collections.Specialized;namespace CustomControls {   [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]   
       public class MyButton: Control, IPostBackEventHandler {
          
          // Defines the Click event.
          public event EventHandler Click;
          
          //Invoke delegates registered with the Click event.
          protected virtual void OnClick(EventArgs e) {
             
             if (Click != null) {
                Click(this, e);
             }   
          }
          
          
          // Define the method of IPostBackEventHandler that raises change events.
          public void RaisePostBackEvent(string eventArgument){
             
             OnClick(new EventArgs());
          }
          
          
          protected override void Render(HtmlTextWriter output) {
             output.Write("<INPUT TYPE = submit name = " + this.UniqueID + 
                " Value = 'Click Me' />");   
          }
       }    
    }
      

  8.   

    郁闷。就上面那个小控件代码也不行吗?那测试后的客户端HTML代码是否有生成呢?
    output.Write("<INPUT TYPE = submit name = " + this.UniqueID + 
                " Value = 'Click Me' />");   改成把Write改成WriteLine这样看看
      

  9.   

    output.WriteLine("<INPUT type=\"submit\" name=\"{0}\" id=\"{0}\" value=\"你好啊\" />", this.UniqueID);
    这样能够正常,就这样,你跟大的例子核对一下,因该没问题的。IPostBackEventHandler接口是要实现的,恩。
      

  10.   

    hackate(兰花开香入梦境,独思佳人亦飘然!!) 
    按钮的ID不能和控件的ID一样吧~~~~~所以按钮的ID是控件的ID+"view"output.Write("<input type =\"submit\" value = \"预览\" id =\"{0}View\" name =\"{0}View\">",UniqueID);IPostBackEventHandler实现了呀~~~
    ---------------------------------------
    public event EventHandler Click;
          
    // Invokes delegates registered with the Click event.
    protected virtual void OnClick(EventArgs e) 
    {     
    if (Click != null) 
    {
    Click(this, e);
    //EventHandler oEventHandler = ( EventHandler )Events[Click] ;
    //if (oEventHandler != null) oEventHandler(this, e);
    }  
    }
    void IPostBackEventHandler.RaisePostBackEvent ( string eventArgument )
    {
    OnClick ( EventArgs.Empty );
    //OnClick(new EventArgs());
    }
    -----------------------------------
      

  11.   

    我的是就你上面那个小例子的,所以没什么差别,要是用符合控件就不行了你上面是实现了,估计就是在你输出控件前台代码的render方法中出了问题吧你仔细看看代码,简单的一点一点加,一点点测试,可能找出问题,太多了。。
      

  12.   

    如果还不行,去掉实现这个接口INamingContainer把这个INamingContainer删除,看看吧估计是这个问题,
      

  13.   

    代码太长了,没有仔细看.说说原理就是了.如果是动态生成的按钮等控件,那么必须要保证按钮点击时的页面和按钮点击后的页面都有这个按钮.
    并且按钮一定要在pageload或者pageload之前事件中生成.
      

  14.   

    受hackate之托过来看看,问题查明。
    你的预览按钮不是服务器端控件,无法触发服务器端事件。
    需要将此按钮改为HtmlEdit的子控件,并使用Bubble Event机制。可能的话帮楼主改一下,楼主等我好消息吧。
      

  15.   

    楼主加上这两个函数,把最后那个Render改一下,就可以调用到OnClick函数了,不过你的Events里面不知道怎么回事取不到Click所绑定的函数,自己再看一下吧。
    protected override void CreateChildControls()
    {
    Controls.Clear();
    ClearChildViewState();
    _preview = new Button();
    _preview.Text = "预览";
    _preview.ID = "Preview"; System.Web.HttpBrowserCapabilities oBrowser = Page.Request.Browser ;
    //对应的IE版本必须是5.5或以上的版本 
    if (oBrowser.Browser == "IE" && oBrowser.MajorVersion >= 5.5 && oBrowser.Win32)
    {
    TableRow row = new TableRow();
    TableCell cell = new TableCell();
    row.Controls.Add(cell);
    HtmlGenericControl  genericControl= new HtmlGenericControl();
    genericControl.InnerHtml = "Your html here";
    cell.Controls.Add(genericControl);
    Controls.Add(row);
    row = new TableRow();
                   cell = new TableCell();
    row.Controls.Add(cell);
    cell.Controls.Add(_preview); Controls.Add(row);
    } base.CreateChildControls ();
    }protected override bool OnBubbleEvent(object source, EventArgs args)
    {
    if(source is Button && ((Button)source).ID == "Preview")
    {
    OnClick(args);
    return true;
    }
    return base.OnBubbleEvent (source, args);
    }//接下来是最重要的怎样把本组件和Editor.aspx结合起来,这里使用的是iframe技术:
    //覆盖Render方法,运行时输出:
    protected override void Render(HtmlTextWriter output)
    {
    EnsureChildControls();
    base.Render(output);
    }
    希望对你有帮助。
      

  16.   

    TO:tmfc() &&  hackate
    非常感谢!!!!
    我看看你修改的东东,有问题还要麻烦你呢~~~
    谢谢~~~~
      

  17.   

    总的来说你这个应该要做成复合控件。因为你的程序是C#的,我不适应,很多东西调试起来很累。。
    而且好像也挺多的,我自己做了个很简单的,也是复合控件,也是继承Controls类的,测试成功通过。基本没问题,如果你看得懂VB。NET,可以发给你参考一下,你就照着这样去做。
    还有你这个控件要改的地方很多你外面应该用一个DIV或者表格把这些render要显示的框架什么的,都加到子控件中去。。按钮的点激等如楼上tmfc朋友所说的处理。。
      

  18.   

    Imports System.ComponentModel
    Imports System
    Imports System.Web.UI
    Imports System.Web.UI.HtmlControls
    Imports System.Web.UI.WebControls<DefaultEvent("Click"), ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")> Public Class WebCustomControl1
        Inherits Control
        Implements INamingContainer    Public Event Click As EventHandler    Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)
            EnsureChildControls()
            output.WriteLine("<div id=""{0}"" name=""{0}"">", Me.ClientID)
            MyBase.RenderChildren(output)
            output.WriteLine("</div>")
        End Sub    Protected Overridable Sub OnClick(ByVal e As EventArgs)
            'Dim loginHandler As EventHandler = CType(Events(_loginClick), EventHandler)
            RaiseEvent Click(Me, e)
        End Sub    Protected Overrides Sub CreateChildControls()
            Controls.Clear()
            ClearChildViewState()
            Dim btn As New Button
            btn.ID = "btn"
            btn.Text = "按钮"
            Controls.Add(btn)
            TrackViewState()
            ChildControlsCreated = True
        End Sub    Protected Overrides Function OnBubbleEvent(ByVal source As Object, ByVal args As System.EventArgs) As Boolean
            If TypeOf source Is Button AndAlso CType(source, Button).ID = "btn" Then
                OnClick(Nothing)
                Return True
            End If
            Return MyBase.OnBubbleEvent(source, args)
        End Function
    End Class代码帖出,如有误点去指出,谢谢,我也刚学不久的,很菜。。
    希望这个代码对你有所帮助!
      

  19.   

    终于搞定了!
    preview  =  new  Button(); 应该是Button _preview  =  new  Button(); 谢谢两位 hackate(兰花开香入梦境,独思佳人亦飘然!!)和tmfc()
    两位都是强人!!!!
    学习,学习......
    分数两位不要嫌少