Problems with button control containing text and image

Discussion in 'ASP .Net Building Controls' started by David, Sep 6, 2006.

  1. David

    David Guest

    Hello all. I am trying to implement my first server control and have
    run into two problems that I cannot solve. I need the assistance of
    someone with more experience.

    My goal was to create an input button that would allow for both text
    and an image on it. I am attempting to accomplish this by basing off
    of the asp:button control. I added a property for the image url and
    one to determine if the image is displayed on the left or right of the
    text. I am also overriding the necessary methods so that the html that
    is rendered is correct. (The code is included below.)

    In my aspx file I put two instances of the control:

    <tlic:ImageTextButton ID="btnSaveAll" runat="server" Text="Save All"
    ImageUrl="Images/Diskette.gif" />
    <tlic:ImageTextButton ID="btnEmailAll" runat="server" Text="Email All"
    ImageUrl="Images/Envelope.gif" OnClientClick="return GetRecipients();"
    />

    It renders the following in the html to the browser:

    <button type="submit" name="btnSaveAll" value="Save All"
    id="btnSaveAll"><img id="btnSaveAll_Img" name="btnSaveAll:Img"
    src="Images/Diskette.gif" border="0" />&nbsp;Save All</button>
    <button type="submit" name="btnEmailAll" value="Email All"
    onclick="return GetRecipients();" language="javascript"
    id="btnEmailAll"><img id="btnEmailAll_Img" name="btnEmailAll:Img"
    src="Images/Envelope.gif" border="0" />&nbsp;Email All</button>

    So far, all is good. The problems come in when I click one of the
    buttons. The first problem is that ASP.NET complains when validating
    the response because the value of the button is being returned as the
    inner html rather than what is in the Value attribute. Since there is
    an IMG tag there it thinks the data is suspect. Here is the form data:

    __EVENTTARGET
    __EVENTARGUMENT
    __VIEWSTATE /wEPDwUKMTgzNj(snip)...
    emailRecipients
    gridAuthKeys:_ctl2:tbRANumber
    gridAuthKeys:_ctl2:tbPONumber
    gridAuthKeys:_ctl2:tbMustArriveBy
    btnSaveAll <IMG id=btnSaveAll_Img src="Images/Diskette.gif" border=0
    name=btnSaveAll:Img>&nbsp;Save All
    btnEmailAll <IMG id=btnEmailAll_Img src="Images/Envelope.gif" border=0
    name=btnEmailAll:Img>&nbsp;Email All

    I figured I would deal with that later so I turned off page validation
    to see if the rest of the processing would work. The second problem is
    that no matter which button I click, ASP.NET fires off the event
    handler for which ever is the last, or second, button, in this case
    "email all". Again, I think the value of the button controls is
    messing it up.

    I tried setting the buttons to UseSubmit=False vs. True but that
    didn't help. An interesting thing to note is that according to the
    HTML spec, if a form contains more than one submit button, only the one
    clicked is supposed to be included in the form data returned. This is
    not what is happening here.

    I would greatly appreciate any time that someone could spend to help me
    with this.

    Regards,

    David

    Here is the code for the control:

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Web
    Imports System.Web.UI
    Imports System.ComponentModel
    Imports System.Drawing.Design

    Namespace TLI.Controls

    ''' <summary>
    ''' A control rendered as a button that has both an image and text.
    ''' </summary>
    ''' <remarks></remarks>
    <ToolboxData("<{0}:ImageTextButton
    runat=server></{0}:ImageTextButton>")> _
    Public Class ImageTextButton
    Inherits WebControls.Button

    <Bindable(True), _
    Category("Appearance"), _
    DefaultValue(""), _
    Editor("System.Windows.Forms.ImageEditorIndex, System.Design",
    GetType(UITypeEditor)), _
    Description("The image to appear on the button")> _
    Public Property ImageUrl() As String
    Get
    Dim s As String = CStr(ViewState("ImageURL"))
    Return IIf(s Is Nothing, "", s)
    End Get
    Set(ByVal value As String)
    ViewState("ImageURL") = value
    End Set
    End Property

    <Bindable(True), _
    Category("Appearance"), _
    DefaultValue(True), _
    Description("True if the image is to appear to the left of the
    text")> _
    Public Property ImageLeft() As Boolean
    Get
    Dim o As Object = ViewState("ImageLeft")
    Return IIf(o Is Nothing, True, CBool(o))
    End Get
    Set(ByVal value As Boolean)
    ViewState("ImageLeft") = value
    End Set
    End Property

    Protected Overrides ReadOnly Property TagKey() As
    HtmlTextWriterTag
    Get
    Return HtmlTextWriterTag.Button
    End Get
    End Property

    Protected Overrides Sub RenderContents(ByVal writer As
    System.Web.UI.HtmlTextWriter)
    If ImageLeft Then
    RenderImage(writer)
    writer.Write("&nbsp;")
    End If
    writer.Write(Text)
    If Not ImageLeft Then
    writer.Write("&nbsp;")
    RenderImage(writer)
    End If
    End Sub

    Private Sub RenderImage(ByVal writer As
    System.Web.UI.HtmlTextWriter)
    writer.AddAttribute(HtmlTextWriterAttribute.Id, ID &
    "_Img")
    writer.AddAttribute(HtmlTextWriterAttribute.Name, ID &
    ":Img")
    writer.AddAttribute(HtmlTextWriterAttribute.Src, ImageUrl)
    writer.AddAttribute(HtmlTextWriterAttribute.Border, "0")
    writer.RenderBeginTag(HtmlTextWriterTag.Img)
    writer.RenderEndTag()
    End Sub
    End Class
    End Namespace
     
    David, Sep 6, 2006
    #1
    1. Advertising

  2. That is a tough one.

    I have a partial fix. I placed your button control onto a page and it
    does blow up in MSIE because it is trying to include HTML markup in the
    value of a response. That is just a security precaution built into
    ASP.NET.

    Dim key1 As String = "Fix-" & ImageTextButton1.ClientID

    If Not Page.ClientScript.IsOnSubmitStatementRegistered(key1)
    Then
    Dim script As String = "if (document.all) {document.all['"
    & ImageTextButton1.ClientID & "'].value = '" & ImageTextButton1.Text &
    "';}"
    Page.ClientScript.RegisterOnSubmitStatement(Me.GetType(),
    key1, script)
    End If

    This is done inside the Load event handler of the page but you can just
    as easily call RegisterOnSubmitStatement from a server control and
    register the Javascript there.

    That at least prevents the markup for the image inside the button tag
    from being included when the form is submitted.

    But then it causes problems on the postback. If you have more than one
    of these image buttons on the page it will cause the last button to be
    the one selected. I am not sure what is causing that.

    But at this point it does not cause that server error.

    Brennan Stehling
    http://brennan.offwhite.net/blog/


    David wrote:
    > Hello all. I am trying to implement my first server control and have
    > run into two problems that I cannot solve. I need the assistance of
    > someone with more experience.
    >
    > My goal was to create an input button that would allow for both text
    > and an image on it. I am attempting to accomplish this by basing off
    > of the asp:button control. I added a property for the image url and
    > one to determine if the image is displayed on the left or right of the
    > text. I am also overriding the necessary methods so that the html that
    > is rendered is correct. (The code is included below.)
    >
    > In my aspx file I put two instances of the control:
    >
    > <tlic:ImageTextButton ID="btnSaveAll" runat="server" Text="Save All"
    > ImageUrl="Images/Diskette.gif" />
    > <tlic:ImageTextButton ID="btnEmailAll" runat="server" Text="Email All"
    > ImageUrl="Images/Envelope.gif" OnClientClick="return GetRecipients();"
    > />
    >
    > It renders the following in the html to the browser:
    >
    > <button type="submit" name="btnSaveAll" value="Save All"
    > id="btnSaveAll"><img id="btnSaveAll_Img" name="btnSaveAll:Img"
    > src="Images/Diskette.gif" border="0" />&nbsp;Save All</button>
    > <button type="submit" name="btnEmailAll" value="Email All"
    > onclick="return GetRecipients();" language="javascript"
    > id="btnEmailAll"><img id="btnEmailAll_Img" name="btnEmailAll:Img"
    > src="Images/Envelope.gif" border="0" />&nbsp;Email All</button>
    >
    > So far, all is good. The problems come in when I click one of the
    > buttons. The first problem is that ASP.NET complains when validating
    > the response because the value of the button is being returned as the
    > inner html rather than what is in the Value attribute. Since there is
    > an IMG tag there it thinks the data is suspect. Here is the form data:
    >
    > __EVENTTARGET
    > __EVENTARGUMENT
    > __VIEWSTATE /wEPDwUKMTgzNj(snip)...
    > emailRecipients
    > gridAuthKeys:_ctl2:tbRANumber
    > gridAuthKeys:_ctl2:tbPONumber
    > gridAuthKeys:_ctl2:tbMustArriveBy
    > btnSaveAll <IMG id=btnSaveAll_Img src="Images/Diskette.gif" border=0
    > name=btnSaveAll:Img>&nbsp;Save All
    > btnEmailAll <IMG id=btnEmailAll_Img src="Images/Envelope.gif" border=0
    > name=btnEmailAll:Img>&nbsp;Email All
    >
    > I figured I would deal with that later so I turned off page validation
    > to see if the rest of the processing would work. The second problem is
    > that no matter which button I click, ASP.NET fires off the event
    > handler for which ever is the last, or second, button, in this case
    > "email all". Again, I think the value of the button controls is
    > messing it up.
    >
    > I tried setting the buttons to UseSubmit=False vs. True but that
    > didn't help. An interesting thing to note is that according to the
    > HTML spec, if a form contains more than one submit button, only the one
    > clicked is supposed to be included in the form data returned. This is
    > not what is happening here.
    >
    > I would greatly appreciate any time that someone could spend to help me
    > with this.
    >
    > Regards,
    >
    > David
    >
    > Here is the code for the control:
    >
    > Imports Microsoft.VisualBasic
    > Imports System
    > Imports System.Web
    > Imports System.Web.UI
    > Imports System.ComponentModel
    > Imports System.Drawing.Design
    >
    > Namespace TLI.Controls
    >
    > ''' <summary>
    > ''' A control rendered as a button that has both an image and text.
    > ''' </summary>
    > ''' <remarks></remarks>
    > <ToolboxData("<{0}:ImageTextButton
    > runat=server></{0}:ImageTextButton>")> _
    > Public Class ImageTextButton
    > Inherits WebControls.Button
    >
    > <Bindable(True), _
    > Category("Appearance"), _
    > DefaultValue(""), _
    > Editor("System.Windows.Forms.ImageEditorIndex, System.Design",
    > GetType(UITypeEditor)), _
    > Description("The image to appear on the button")> _
    > Public Property ImageUrl() As String
    > Get
    > Dim s As String = CStr(ViewState("ImageURL"))
    > Return IIf(s Is Nothing, "", s)
    > End Get
    > Set(ByVal value As String)
    > ViewState("ImageURL") = value
    > End Set
    > End Property
    >
    > <Bindable(True), _
    > Category("Appearance"), _
    > DefaultValue(True), _
    > Description("True if the image is to appear to the left of the
    > text")> _
    > Public Property ImageLeft() As Boolean
    > Get
    > Dim o As Object = ViewState("ImageLeft")
    > Return IIf(o Is Nothing, True, CBool(o))
    > End Get
    > Set(ByVal value As Boolean)
    > ViewState("ImageLeft") = value
    > End Set
    > End Property
    >
    > Protected Overrides ReadOnly Property TagKey() As
    > HtmlTextWriterTag
    > Get
    > Return HtmlTextWriterTag.Button
    > End Get
    > End Property
    >
    > Protected Overrides Sub RenderContents(ByVal writer As
    > System.Web.UI.HtmlTextWriter)
    > If ImageLeft Then
    > RenderImage(writer)
    > writer.Write("&nbsp;")
    > End If
    > writer.Write(Text)
    > If Not ImageLeft Then
    > writer.Write("&nbsp;")
    > RenderImage(writer)
    > End If
    > End Sub
    >
    > Private Sub RenderImage(ByVal writer As
    > System.Web.UI.HtmlTextWriter)
    > writer.AddAttribute(HtmlTextWriterAttribute.Id, ID &
    > "_Img")
    > writer.AddAttribute(HtmlTextWriterAttribute.Name, ID &
    > ":Img")
    > writer.AddAttribute(HtmlTextWriterAttribute.Src, ImageUrl)
    > writer.AddAttribute(HtmlTextWriterAttribute.Border, "0")
    > writer.RenderBeginTag(HtmlTextWriterTag.Img)
    > writer.RenderEndTag()
    > End Sub
    > End Class
    > End Namespace
     
    Brennan Stehling, Sep 7, 2006
    #2
    1. Advertising

  3. David

    David Guest

    Brennan,

    Thanks for the help here. Your code does indeed take care of the
    validation issue. I will keep working on the postback issue. Let me
    know if you have an epiphany.

    Thanks again.

    David
    ----------------------------------------------------------
    Brennan Stehling wrote:
    > That is a tough one.
    >
    > I have a partial fix. I placed your button control onto a page and it
    > does blow up in MSIE because it is trying to include HTML markup in the
    > value of a response. That is just a security precaution built into
    > ASP.NET.
    >
    > Dim key1 As String = "Fix-" & ImageTextButton1.ClientID
    >
    > If Not Page.ClientScript.IsOnSubmitStatementRegistered(key1)
    > Then
    > Dim script As String = "if (document.all) {document.all['"
    > & ImageTextButton1.ClientID & "'].value = '" & ImageTextButton1.Text &
    > "';}"
    > Page.ClientScript.RegisterOnSubmitStatement(Me.GetType(),
    > key1, script)
    > End If
    >
    > This is done inside the Load event handler of the page but you can just
    > as easily call RegisterOnSubmitStatement from a server control and
    > register the Javascript there.
    >
    > That at least prevents the markup for the image inside the button tag
    > from being included when the form is submitted.
    >
    > But then it causes problems on the postback. If you have more than one
    > of these image buttons on the page it will cause the last button to be
    > the one selected. I am not sure what is causing that.
    >
    > But at this point it does not cause that server error.
    >
    > Brennan Stehling
    > http://brennan.offwhite.net/blog/
    >
    >
    > David wrote:
    > > Hello all. I am trying to implement my first server control and have
    > > run into two problems that I cannot solve. I need the assistance of
    > > someone with more experience.
    > >
    > > My goal was to create an input button that would allow for both text
    > > and an image on it. I am attempting to accomplish this by basing off
    > > of the asp:button control. I added a property for the image url and
    > > one to determine if the image is displayed on the left or right of the
    > > text. I am also overriding the necessary methods so that the html that
    > > is rendered is correct. (The code is included below.)
    > >
    > > In my aspx file I put two instances of the control:
    > >
    > > <tlic:ImageTextButton ID="btnSaveAll" runat="server" Text="Save All"
    > > ImageUrl="Images/Diskette.gif" />
    > > <tlic:ImageTextButton ID="btnEmailAll" runat="server" Text="Email All"
    > > ImageUrl="Images/Envelope.gif" OnClientClick="return GetRecipients();"
    > > />
    > >
    > > It renders the following in the html to the browser:
    > >
    > > <button type="submit" name="btnSaveAll" value="Save All"
    > > id="btnSaveAll"><img id="btnSaveAll_Img" name="btnSaveAll:Img"
    > > src="Images/Diskette.gif" border="0" />&nbsp;Save All</button>
    > > <button type="submit" name="btnEmailAll" value="Email All"
    > > onclick="return GetRecipients();" language="javascript"
    > > id="btnEmailAll"><img id="btnEmailAll_Img" name="btnEmailAll:Img"
    > > src="Images/Envelope.gif" border="0" />&nbsp;Email All</button>
    > >
    > > So far, all is good. The problems come in when I click one of the
    > > buttons. The first problem is that ASP.NET complains when validating
    > > the response because the value of the button is being returned as the
    > > inner html rather than what is in the Value attribute. Since there is
    > > an IMG tag there it thinks the data is suspect. Here is the form data:
    > >
    > > __EVENTTARGET
    > > __EVENTARGUMENT
    > > __VIEWSTATE /wEPDwUKMTgzNj(snip)...
    > > emailRecipients
    > > gridAuthKeys:_ctl2:tbRANumber
    > > gridAuthKeys:_ctl2:tbPONumber
    > > gridAuthKeys:_ctl2:tbMustArriveBy
    > > btnSaveAll <IMG id=btnSaveAll_Img src="Images/Diskette.gif" border=0
    > > name=btnSaveAll:Img>&nbsp;Save All
    > > btnEmailAll <IMG id=btnEmailAll_Img src="Images/Envelope.gif" border=0
    > > name=btnEmailAll:Img>&nbsp;Email All
    > >
    > > I figured I would deal with that later so I turned off page validation
    > > to see if the rest of the processing would work. The second problem is
    > > that no matter which button I click, ASP.NET fires off the event
    > > handler for which ever is the last, or second, button, in this case
    > > "email all". Again, I think the value of the button controls is
    > > messing it up.
    > >
    > > I tried setting the buttons to UseSubmit=False vs. True but that
    > > didn't help. An interesting thing to note is that according to the
    > > HTML spec, if a form contains more than one submit button, only the one
    > > clicked is supposed to be included in the form data returned. This is
    > > not what is happening here.
    > >
    > > I would greatly appreciate any time that someone could spend to help me
    > > with this.
    > >
    > > Regards,
    > >
    > > David
    > >
    > > Here is the code for the control:
    > >
    > > Imports Microsoft.VisualBasic
    > > Imports System
    > > Imports System.Web
    > > Imports System.Web.UI
    > > Imports System.ComponentModel
    > > Imports System.Drawing.Design
    > >
    > > Namespace TLI.Controls
    > >
    > > ''' <summary>
    > > ''' A control rendered as a button that has both an image and text.
    > > ''' </summary>
    > > ''' <remarks></remarks>
    > > <ToolboxData("<{0}:ImageTextButton
    > > runat=server></{0}:ImageTextButton>")> _
    > > Public Class ImageTextButton
    > > Inherits WebControls.Button
    > >
    > > <Bindable(True), _
    > > Category("Appearance"), _
    > > DefaultValue(""), _
    > > Editor("System.Windows.Forms.ImageEditorIndex, System.Design",
    > > GetType(UITypeEditor)), _
    > > Description("The image to appear on the button")> _
    > > Public Property ImageUrl() As String
    > > Get
    > > Dim s As String = CStr(ViewState("ImageURL"))
    > > Return IIf(s Is Nothing, "", s)
    > > End Get
    > > Set(ByVal value As String)
    > > ViewState("ImageURL") = value
    > > End Set
    > > End Property
    > >
    > > <Bindable(True), _
    > > Category("Appearance"), _
    > > DefaultValue(True), _
    > > Description("True if the image is to appear to the left of the
    > > text")> _
    > > Public Property ImageLeft() As Boolean
    > > Get
    > > Dim o As Object = ViewState("ImageLeft")
    > > Return IIf(o Is Nothing, True, CBool(o))
    > > End Get
    > > Set(ByVal value As Boolean)
    > > ViewState("ImageLeft") = value
    > > End Set
    > > End Property
    > >
    > > Protected Overrides ReadOnly Property TagKey() As
    > > HtmlTextWriterTag
    > > Get
    > > Return HtmlTextWriterTag.Button
    > > End Get
    > > End Property
    > >
    > > Protected Overrides Sub RenderContents(ByVal writer As
    > > System.Web.UI.HtmlTextWriter)
    > > If ImageLeft Then
    > > RenderImage(writer)
    > > writer.Write("&nbsp;")
    > > End If
    > > writer.Write(Text)
    > > If Not ImageLeft Then
    > > writer.Write("&nbsp;")
    > > RenderImage(writer)
    > > End If
    > > End Sub
    > >
    > > Private Sub RenderImage(ByVal writer As
    > > System.Web.UI.HtmlTextWriter)
    > > writer.AddAttribute(HtmlTextWriterAttribute.Id, ID &
    > > "_Img")
    > > writer.AddAttribute(HtmlTextWriterAttribute.Name, ID &
    > > ":Img")
    > > writer.AddAttribute(HtmlTextWriterAttribute.Src, ImageUrl)
    > > writer.AddAttribute(HtmlTextWriterAttribute.Border, "0")
    > > writer.RenderBeginTag(HtmlTextWriterTag.Img)
    > > writer.RenderEndTag()
    > > End Sub
    > > End Class
    > > End Namespace
     
    David, Sep 7, 2006
    #3
  4. David

    David Guest

    I hit on a solution to get this to work. Evidently when IE submits the
    form, it includes in the form data all elements of the <button>
    variety, regardless of whether they are typed as Submit or Button.
    This is messing up ASP.NET in that it must look through the form data
    returned and assume that a button in the form data means that the
    button was clicked. When it finds more than one, it takes the last one
    in the form. This is true even if you are not using the submit
    behavior of the button but are using the __doPostBack functionality
    which sets the __EVENTTARGET variable.

    So, I altered Brennan's code slightly and when submitting the form I
    disable the buttons instead of changing their value. This coupled with
    the control forcing the UseSubmitBehavior to false prevents the buttons
    from being in the submitted form data so ASP.NET then uses the
    __EVENTTARGET.

    David wrote:
    > Brennan,
    >
    > Thanks for the help here. Your code does indeed take care of the
    > validation issue. I will keep working on the postback issue. Let me
    > know if you have an epiphany.
    >
    > Thanks again.
    >
    > David
    > ----------------------------------------------------------
    > Brennan Stehling wrote:
    > > That is a tough one.
    > >
    > > I have a partial fix. I placed your button control onto a page and it
    > > does blow up in MSIE because it is trying to include HTML markup in the
    > > value of a response. That is just a security precaution built into
    > > ASP.NET.
    > >
    > > Dim key1 As String = "Fix-" & ImageTextButton1.ClientID
    > >
    > > If Not Page.ClientScript.IsOnSubmitStatementRegistered(key1)
    > > Then
    > > Dim script As String = "if (document.all) {document.all['"
    > > & ImageTextButton1.ClientID & "'].value = '" & ImageTextButton1.Text &
    > > "';}"
    > > Page.ClientScript.RegisterOnSubmitStatement(Me.GetType(),
    > > key1, script)
    > > End If
    > >
    > > This is done inside the Load event handler of the page but you can just
    > > as easily call RegisterOnSubmitStatement from a server control and
    > > register the Javascript there.
    > >
    > > That at least prevents the markup for the image inside the button tag
    > > from being included when the form is submitted.
    > >
    > > But then it causes problems on the postback. If you have more than one
    > > of these image buttons on the page it will cause the last button to be
    > > the one selected. I am not sure what is causing that.
    > >
    > > But at this point it does not cause that server error.
    > >
    > > Brennan Stehling
    > > http://brennan.offwhite.net/blog/
    > >
    > >
    > > David wrote:
    > > > Hello all. I am trying to implement my first server control and have
    > > > run into two problems that I cannot solve. I need the assistance of
    > > > someone with more experience.
    > > >
    > > > My goal was to create an input button that would allow for both text
    > > > and an image on it. I am attempting to accomplish this by basing off
    > > > of the asp:button control. I added a property for the image url and
    > > > one to determine if the image is displayed on the left or right of the
    > > > text. I am also overriding the necessary methods so that the html that
    > > > is rendered is correct. (The code is included below.)
    > > >
    > > > In my aspx file I put two instances of the control:
    > > >
    > > > <tlic:ImageTextButton ID="btnSaveAll" runat="server" Text="Save All"
    > > > ImageUrl="Images/Diskette.gif" />
    > > > <tlic:ImageTextButton ID="btnEmailAll" runat="server" Text="Email All"
    > > > ImageUrl="Images/Envelope.gif" OnClientClick="return GetRecipients();"
    > > > />
    > > >
    > > > It renders the following in the html to the browser:
    > > >
    > > > <button type="submit" name="btnSaveAll" value="Save All"
    > > > id="btnSaveAll"><img id="btnSaveAll_Img" name="btnSaveAll:Img"
    > > > src="Images/Diskette.gif" border="0" />&nbsp;Save All</button>
    > > > <button type="submit" name="btnEmailAll" value="Email All"
    > > > onclick="return GetRecipients();" language="javascript"
    > > > id="btnEmailAll"><img id="btnEmailAll_Img" name="btnEmailAll:Img"
    > > > src="Images/Envelope.gif" border="0" />&nbsp;Email All</button>
    > > >
    > > > So far, all is good. The problems come in when I click one of the
    > > > buttons. The first problem is that ASP.NET complains when validating
    > > > the response because the value of the button is being returned as the
    > > > inner html rather than what is in the Value attribute. Since there is
    > > > an IMG tag there it thinks the data is suspect. Here is the form data:
    > > >
    > > > __EVENTTARGET
    > > > __EVENTARGUMENT
    > > > __VIEWSTATE /wEPDwUKMTgzNj(snip)...
    > > > emailRecipients
    > > > gridAuthKeys:_ctl2:tbRANumber
    > > > gridAuthKeys:_ctl2:tbPONumber
    > > > gridAuthKeys:_ctl2:tbMustArriveBy
    > > > btnSaveAll <IMG id=btnSaveAll_Img src="Images/Diskette.gif" border=0
    > > > name=btnSaveAll:Img>&nbsp;Save All
    > > > btnEmailAll <IMG id=btnEmailAll_Img src="Images/Envelope.gif" border=0
    > > > name=btnEmailAll:Img>&nbsp;Email All
    > > >
    > > > I figured I would deal with that later so I turned off page validation
    > > > to see if the rest of the processing would work. The second problem is
    > > > that no matter which button I click, ASP.NET fires off the event
    > > > handler for which ever is the last, or second, button, in this case
    > > > "email all". Again, I think the value of the button controls is
    > > > messing it up.
    > > >
    > > > I tried setting the buttons to UseSubmit=False vs. True but that
    > > > didn't help. An interesting thing to note is that according to the
    > > > HTML spec, if a form contains more than one submit button, only the one
    > > > clicked is supposed to be included in the form data returned. This is
    > > > not what is happening here.
    > > >
    > > > I would greatly appreciate any time that someone could spend to help me
    > > > with this.
    > > >
    > > > Regards,
    > > >
    > > > David
    > > >
    > > > Here is the code for the control:
    > > >
    > > > Imports Microsoft.VisualBasic
    > > > Imports System
    > > > Imports System.Web
    > > > Imports System.Web.UI
    > > > Imports System.ComponentModel
    > > > Imports System.Drawing.Design
    > > >
    > > > Namespace TLI.Controls
    > > >
    > > > ''' <summary>
    > > > ''' A control rendered as a button that has both an image and text.
    > > > ''' </summary>
    > > > ''' <remarks></remarks>
    > > > <ToolboxData("<{0}:ImageTextButton
    > > > runat=server></{0}:ImageTextButton>")> _
    > > > Public Class ImageTextButton
    > > > Inherits WebControls.Button
    > > >
    > > > <Bindable(True), _
    > > > Category("Appearance"), _
    > > > DefaultValue(""), _
    > > > Editor("System.Windows.Forms.ImageEditorIndex, System.Design",
    > > > GetType(UITypeEditor)), _
    > > > Description("The image to appear on the button")> _
    > > > Public Property ImageUrl() As String
    > > > Get
    > > > Dim s As String = CStr(ViewState("ImageURL"))
    > > > Return IIf(s Is Nothing, "", s)
    > > > End Get
    > > > Set(ByVal value As String)
    > > > ViewState("ImageURL") = value
    > > > End Set
    > > > End Property
    > > >
    > > > <Bindable(True), _
    > > > Category("Appearance"), _
    > > > DefaultValue(True), _
    > > > Description("True if the image is to appear to the left of the
    > > > text")> _
    > > > Public Property ImageLeft() As Boolean
    > > > Get
    > > > Dim o As Object = ViewState("ImageLeft")
    > > > Return IIf(o Is Nothing, True, CBool(o))
    > > > End Get
    > > > Set(ByVal value As Boolean)
    > > > ViewState("ImageLeft") = value
    > > > End Set
    > > > End Property
    > > >
    > > > Protected Overrides ReadOnly Property TagKey() As
    > > > HtmlTextWriterTag
    > > > Get
    > > > Return HtmlTextWriterTag.Button
    > > > End Get
    > > > End Property
    > > >
    > > > Protected Overrides Sub RenderContents(ByVal writer As
    > > > System.Web.UI.HtmlTextWriter)
    > > > If ImageLeft Then
    > > > RenderImage(writer)
    > > > writer.Write("&nbsp;")
    > > > End If
    > > > writer.Write(Text)
    > > > If Not ImageLeft Then
    > > > writer.Write("&nbsp;")
    > > > RenderImage(writer)
    > > > End If
    > > > End Sub
    > > >
    > > > Private Sub RenderImage(ByVal writer As
    > > > System.Web.UI.HtmlTextWriter)
    > > > writer.AddAttribute(HtmlTextWriterAttribute.Id, ID &
    > > > "_Img")
    > > > writer.AddAttribute(HtmlTextWriterAttribute.Name, ID &
    > > > ":Img")
    > > > writer.AddAttribute(HtmlTextWriterAttribute.Src, ImageUrl)
    > > > writer.AddAttribute(HtmlTextWriterAttribute.Border, "0")
    > > > writer.RenderBeginTag(HtmlTextWriterTag.Img)
    > > > writer.RenderEndTag()
    > > > End Sub
    > > > End Class
    > > > End Namespace
     
    David, Sep 7, 2006
    #4
  5. David,

    That solution works great. I posted my test page here...

    http://www.offwhite.net/ButtonBug/

    Brennan Stehling
    http://brennan.offwhite.net/blog/

    David wrote:
    > I hit on a solution to get this to work. Evidently when IE submits the
    > form, it includes in the form data all elements of the <button>
    > variety, regardless of whether they are typed as Submit or Button.
    > This is messing up ASP.NET in that it must look through the form data
    > returned and assume that a button in the form data means that the
    > button was clicked. When it finds more than one, it takes the last one
    > in the form. This is true even if you are not using the submit
    > behavior of the button but are using the __doPostBack functionality
    > which sets the __EVENTTARGET variable.
    >
    > So, I altered Brennan's code slightly and when submitting the form I
    > disable the buttons instead of changing their value. This coupled with
    > the control forcing the UseSubmitBehavior to false prevents the buttons
    > from being in the submitted form data so ASP.NET then uses the
    > __EVENTTARGET.
    >
    > David wrote:
    > > Brennan,
    > >
    > > Thanks for the help here. Your code does indeed take care of the
    > > validation issue. I will keep working on the postback issue. Let me
    > > know if you have an epiphany.
    > >
    > > Thanks again.
    > >
    > > David
    > > ----------------------------------------------------------
    > > Brennan Stehling wrote:
    > > > That is a tough one.
    > > >
    > > > I have a partial fix. I placed your button control onto a page and it
    > > > does blow up in MSIE because it is trying to include HTML markup in the
    > > > value of a response. That is just a security precaution built into
    > > > ASP.NET.
    > > >
    > > > Dim key1 As String = "Fix-" & ImageTextButton1.ClientID
    > > >
    > > > If Not Page.ClientScript.IsOnSubmitStatementRegistered(key1)
    > > > Then
    > > > Dim script As String = "if (document.all) {document.all['"
    > > > & ImageTextButton1.ClientID & "'].value = '" & ImageTextButton1.Text &
    > > > "';}"
    > > > Page.ClientScript.RegisterOnSubmitStatement(Me.GetType(),
    > > > key1, script)
    > > > End If
    > > >
    > > > This is done inside the Load event handler of the page but you can just
    > > > as easily call RegisterOnSubmitStatement from a server control and
    > > > register the Javascript there.
    > > >
    > > > That at least prevents the markup for the image inside the button tag
    > > > from being included when the form is submitted.
    > > >
    > > > But then it causes problems on the postback. If you have more than one
    > > > of these image buttons on the page it will cause the last button to be
    > > > the one selected. I am not sure what is causing that.
    > > >
    > > > But at this point it does not cause that server error.
    > > >
    > > > Brennan Stehling
    > > > http://brennan.offwhite.net/blog/
    > > >
    > > >
    > > > David wrote:
    > > > > Hello all. I am trying to implement my first server control and have
    > > > > run into two problems that I cannot solve. I need the assistance of
    > > > > someone with more experience.
    > > > >
    > > > > My goal was to create an input button that would allow for both text
    > > > > and an image on it. I am attempting to accomplish this by basing off
    > > > > of the asp:button control. I added a property for the image url and
    > > > > one to determine if the image is displayed on the left or right of the
    > > > > text. I am also overriding the necessary methods so that the html that
    > > > > is rendered is correct. (The code is included below.)
    > > > >
    > > > > In my aspx file I put two instances of the control:
    > > > >
    > > > > <tlic:ImageTextButton ID="btnSaveAll" runat="server" Text="Save All"
    > > > > ImageUrl="Images/Diskette.gif" />
    > > > > <tlic:ImageTextButton ID="btnEmailAll" runat="server" Text="Email All"
    > > > > ImageUrl="Images/Envelope.gif" OnClientClick="return GetRecipients();"
    > > > > />
    > > > >
    > > > > It renders the following in the html to the browser:
    > > > >
    > > > > <button type="submit" name="btnSaveAll" value="Save All"
    > > > > id="btnSaveAll"><img id="btnSaveAll_Img" name="btnSaveAll:Img"
    > > > > src="Images/Diskette.gif" border="0" />&nbsp;Save All</button>
    > > > > <button type="submit" name="btnEmailAll" value="Email All"
    > > > > onclick="return GetRecipients();" language="javascript"
    > > > > id="btnEmailAll"><img id="btnEmailAll_Img" name="btnEmailAll:Img"
    > > > > src="Images/Envelope.gif" border="0" />&nbsp;Email All</button>
    > > > >
    > > > > So far, all is good. The problems come in when I click one of the
    > > > > buttons. The first problem is that ASP.NET complains when validating
    > > > > the response because the value of the button is being returned as the
    > > > > inner html rather than what is in the Value attribute. Since there is
    > > > > an IMG tag there it thinks the data is suspect. Here is the form data:
    > > > >
    > > > > __EVENTTARGET
    > > > > __EVENTARGUMENT
    > > > > __VIEWSTATE /wEPDwUKMTgzNj(snip)...
    > > > > emailRecipients
    > > > > gridAuthKeys:_ctl2:tbRANumber
    > > > > gridAuthKeys:_ctl2:tbPONumber
    > > > > gridAuthKeys:_ctl2:tbMustArriveBy
    > > > > btnSaveAll <IMG id=btnSaveAll_Img src="Images/Diskette.gif" border=0
    > > > > name=btnSaveAll:Img>&nbsp;Save All
    > > > > btnEmailAll <IMG id=btnEmailAll_Img src="Images/Envelope.gif" border=0
    > > > > name=btnEmailAll:Img>&nbsp;Email All
    > > > >
    > > > > I figured I would deal with that later so I turned off page validation
    > > > > to see if the rest of the processing would work. The second problem is
    > > > > that no matter which button I click, ASP.NET fires off the event
    > > > > handler for which ever is the last, or second, button, in this case
    > > > > "email all". Again, I think the value of the button controls is
    > > > > messing it up.
    > > > >
    > > > > I tried setting the buttons to UseSubmit=False vs. True but that
    > > > > didn't help. An interesting thing to note is that according to the
    > > > > HTML spec, if a form contains more than one submit button, only the one
    > > > > clicked is supposed to be included in the form data returned. This is
    > > > > not what is happening here.
    > > > >
    > > > > I would greatly appreciate any time that someone could spend to help me
    > > > > with this.
    > > > >
    > > > > Regards,
    > > > >
    > > > > David
    > > > >
    > > > > Here is the code for the control:
    > > > >
    > > > > Imports Microsoft.VisualBasic
    > > > > Imports System
    > > > > Imports System.Web
    > > > > Imports System.Web.UI
    > > > > Imports System.ComponentModel
    > > > > Imports System.Drawing.Design
    > > > >
    > > > > Namespace TLI.Controls
    > > > >
    > > > > ''' <summary>
    > > > > ''' A control rendered as a button that has both an image and text.
    > > > > ''' </summary>
    > > > > ''' <remarks></remarks>
    > > > > <ToolboxData("<{0}:ImageTextButton
    > > > > runat=server></{0}:ImageTextButton>")> _
    > > > > Public Class ImageTextButton
    > > > > Inherits WebControls.Button
    > > > >
    > > > > <Bindable(True), _
    > > > > Category("Appearance"), _
    > > > > DefaultValue(""), _
    > > > > Editor("System.Windows.Forms.ImageEditorIndex, System.Design",
    > > > > GetType(UITypeEditor)), _
    > > > > Description("The image to appear on the button")> _
    > > > > Public Property ImageUrl() As String
    > > > > Get
    > > > > Dim s As String = CStr(ViewState("ImageURL"))
    > > > > Return IIf(s Is Nothing, "", s)
    > > > > End Get
    > > > > Set(ByVal value As String)
    > > > > ViewState("ImageURL") = value
    > > > > End Set
    > > > > End Property
    > > > >
    > > > > <Bindable(True), _
    > > > > Category("Appearance"), _
    > > > > DefaultValue(True), _
    > > > > Description("True if the image is to appear to the left of the
    > > > > text")> _
    > > > > Public Property ImageLeft() As Boolean
    > > > > Get
    > > > > Dim o As Object = ViewState("ImageLeft")
    > > > > Return IIf(o Is Nothing, True, CBool(o))
    > > > > End Get
    > > > > Set(ByVal value As Boolean)
    > > > > ViewState("ImageLeft") = value
    > > > > End Set
    > > > > End Property
    > > > >
    > > > > Protected Overrides ReadOnly Property TagKey() As
    > > > > HtmlTextWriterTag
    > > > > Get
    > > > > Return HtmlTextWriterTag.Button
    > > > > End Get
    > > > > End Property
    > > > >
    > > > > Protected Overrides Sub RenderContents(ByVal writer As
    > > > > System.Web.UI.HtmlTextWriter)
    > > > > If ImageLeft Then
    > > > > RenderImage(writer)
    > > > > writer.Write("&nbsp;")
    > > > > End If
    > > > > writer.Write(Text)
    > > > > If Not ImageLeft Then
    > > > > writer.Write("&nbsp;")
    > > > > RenderImage(writer)
    > > > > End If
    > > > > End Sub
    > > > >
    > > > > Private Sub RenderImage(ByVal writer As
    > > > > System.Web.UI.HtmlTextWriter)
    > > > > writer.AddAttribute(HtmlTextWriterAttribute.Id, ID &
    > > > > "_Img")
    > > > > writer.AddAttribute(HtmlTextWriterAttribute.Name, ID &
    > > > > ":Img")
    > > > > writer.AddAttribute(HtmlTextWriterAttribute.Src, ImageUrl)
    > > > > writer.AddAttribute(HtmlTextWriterAttribute.Border, "0")
    > > > > writer.RenderBeginTag(HtmlTextWriterTag.Img)
    > > > > writer.RenderEndTag()
    > > > > End Sub
    > > > > End Class
    > > > > End Namespace
     
    Brennan Stehling, Sep 7, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Amy
    Replies:
    0
    Views:
    1,035
  2. John Smith
    Replies:
    0
    Views:
    1,017
    John Smith
    Aug 2, 2006
  3. David
    Replies:
    1
    Views:
    3,047
    wwwtar
    Nov 30, 2006
  4. Jim Gilligan
    Replies:
    0
    Views:
    175
    Jim Gilligan
    Sep 1, 2005
  5. David Thielen

    Login control - image button with text over it

    David Thielen, Nov 12, 2006, in forum: ASP .Net Web Controls
    Replies:
    13
    Views:
    531
    MikeS
    Nov 16, 2006
Loading...

Share This Page