I'm trying to add Google Adword conversion code script to certain aspx pages in our website but I'm running into an issue with the site using master pages. The Google instruction said to place the code before the body tag but with master pages being used the code will be on all the pages using the master page. I would like setup it up where certain pages use individual conversion codes with others not using anything. Any suggestions or examples would be appreciated. Also, I'm using C#.
Jamal
There are lots of different ways to communicate with controls on Master pages from individual pages. One of them is to create some simple custom controls and use the same pattern .NET uses with it's ScriptManager/ScriptManagerProxy controls. Basically, you put can a ScriptManager control on a Master page with default settings, then if you need to override the defaults on a page, you use a ScriptManagerProxy control.
I don't really know all that's involved with Adwords conversion code, but you could create the custom controls something like this:
AdwordConversionControl:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SATest
{
[DefaultProperty("ConversionCode")]
[ToolboxData("<{0}:AdwordConversion runat=server></{0}:AdwordConversion>")]
public class AdwordConversion : Control
{
private const string _conversionCodeKey = "cc";
private const string _includeScriptKey = "ic";
[Category("Behavior")]
[DefaultValue("")]
public string ConversionCode
{
get { return (String)(ViewState[_conversionCodeKey] ?? "" ); }
set { ViewState[_conversionCodeKey] = value; }
}
[Category("Behavior")]
[DefaultValue(false)]
public bool IncludeScript
{
get { return (bool)(ViewState[_includeScriptKey] ?? false ); }
set { ViewState[_includeScriptKey] = value; }
}
protected override void Render(HtmlTextWriter writer)
{
if ( !IncludeScript ) { return; }
string js = "<script type=\"text/javascript\">...Insert conversion code here: var code = " + ConversionCode + ";</script>";
writer.Write( js );
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if ( Page.Items.Contains( typeof(AdwordConversion) ) )
{
throw new ApplicationException( "There can be only one AdwordConversion control defined on a page. Use AdwordConversionProxy." );
}
Page.Items[typeof(AdwordConversion)] = this;
}
}
}
AdwordConversionProxy Control:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SATest
{
[DefaultProperty("ConversionCode")]
[ToolboxData("<{0}:AdwordConversionProxy runat=server></{0}:AdwordConversionProxy>")]
public class AdwordConversionProxy : Control
{
private string _conversionCode;
private bool? _includeScript;
public string ConversionCode
{
get { return _conversionCode; }
set { _conversionCode = value; }
}
public bool IncludeScript
{
get { return ( _includeScript.HasValue ) ? _includeScript.Value : false; }
set { _includeScript = value; }
}
protected override void Render(HtmlTextWriter writer)
{
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
AdwordConversion current = Page.Items[typeof(AdwordConversion)] as AdwordConversion;
if ( current == null )
{
throw new ApplicationException( "AdwordConversionProxy requires that an AdwordConversion control already exist on a page." );
}
if ( _conversionCode != null )
{
current.ConversionCode = _conversionCode;
}
if ( _includeScript.HasValue )
{
current.IncludeScript = _includeScript.Value;
}
}
}
}
Then you would just put an AdwordConversion control on your master page with default values, and you would put AdwordConversionProxy controls on the individual pages that needed their own settings.
Related
I have a specific requirement to create a user control with specific common functions. To that control I also have the requirement to allow other developers to add controls in designer mode to make specific UI's. To do this I created a user control, adding (sample) label, and button. I also added a panel to allow adding of addition controls in a specific area of the control.
I then made the made the class visible in designer mode by adding [Designer] markup and a [ControlDesigner]. This gives the desired effect to add a User control with some fixed content, and add more controls to the page. The problem is that the panel can be moved by the user in design mode, and VisualStudio gets confused, creating a circular reference.. I must be missing something? Can I turn off the resizing/positioning of the panel, even though I need design mode enabled?
NOTE: I also tried to just use a user control in design mode, but added controls keep disappearing behind the fixed controls on the User Control.
Code and examples are below.. Any suggestion/fixes welcomed..
Above is the visual of the user control with the panel
Above is a form including the User control, and adding a custom button to the panel.. Note the panel drag is enable, if touched, a circular reference gets created in the form.designer.cs file, and the project becomes unstable.
Finally below is the class for User Control
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Windows.Forms.Design;
namespace wfcLib
{
[DesignerAttribute(typeof(MyControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ucInput : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel InternalPanel
{
get { return pnlContent; }
set { pnlContent = value; }
}
public ucInput()
{
InitializeComponent();
}
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyControlDesigner : System.Windows.Forms.Design.ControlDesigner
{
public override void Initialize(IComponent c)
{
base.Initialize(c);
ucInput ctl = (ucInput)c;
EnableDesignMode(ctl.InternalPanel, "InternalPanel");
}
}
}
In addition to my comment concerning using a derived Panel with its own designer that overrides the SelectionRules property, another method would be to tap into the designer's ISelectionService to detect a change in selected components and remove the panel if it was selected.
This is accomplished by overriding the control's Site property to set the hook. Also note that I changed the InternalPanel property to be read-only as you really do not want that writable.
[DesignerAttribute(typeof(MyControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ucInput : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel InternalPanel
{
get { return pnlContent; }
}
public ucInput()
{
InitializeComponent();
}
private ISelectionService selectionService;
private IDesignerHost host;
public override ISite Site
{
get
{
return base.Site;
}
set
{
host = null;
UnSubscribeFromSelectionService();
base.Site = value;
if (value != null)
{
host = (IDesignerHost)this.Site.GetService(typeof(IDesignerHost));
if (host != null)
{
if (host.Loading)
{
// defer subscription to selection service until fully loaded
host.Activated += Host_Activated;
}
else
{
SubscribeToSelectionService();
}
}
}
}
}
private void Host_Activated(object sender, EventArgs e)
{
host.Activated -= Host_Activated;
SubscribeToSelectionService();
}
private void SubscribeToSelectionService()
{
selectionService = (ISelectionService)this.Site.GetService(typeof(ISelectionService));
if (selectionService != null)
{
selectionService.SelectionChanging += OnSelectionChanging;
}
}
private void UnSubscribeFromSelectionService()
{
if (selectionService != null)
{
selectionService.SelectionChanging -= OnSelectionChanging;
}
}
private void OnSelectionChanging(object sender, EventArgs e)
{
if (selectionService.GetComponentSelected(pnlContent))
{
selectionService.SelectionChanging -= OnSelectionChanging;
selectionService.SetSelectedComponents(new[] { pnlContent }, SelectionTypes.Remove);
selectionService.SelectionChanging += OnSelectionChanging;
}
}
}
Edit: The original code neglected to account for SelectionService not being available while the IDesignerHost is loading. Added code to defer subscription until the IDesignerHost is activated.
I've already created my custom textbox control inheriting from it and all is fine and dandy. However, I'm having an issue trying the same thing with a DropDownList. I've searched for about 2 hours in Google and all the results I get are either crappy links or some (uncomplete) suggestions on creating a composite control and adding the DropDownList inside, but that also means that I have to expose all the events and properties that I use, which I find pretty overkill for what I need to do, which is to add a validator of any kind next to my DropDownList control.
To illustrate, this is what I'm attempting to do:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
namespace Blah
{
public class ExtendedDropDownList : DropDownList
{
private DropDownList _self;
private CustomValidator _cv;
public bool Required { get; set; }
public String FieldName { get; set; }
protected override void OnInit(EventArgs e)
{
_cv = new CustomValidator()
{
ControlToValidate = ID,
EnableClientScript = false,
ValidationGroup = ValidationGroup,
ValidateEmptyText = true
};
_cv.ServerValidate += new ServerValidateEventHandler(_cv_ServerValidate);
Controls.Add(_cv);
}
private void _cv_ServerValidate(object source, ServerValidateEventArgs args)
{
if (Required && String.IsNullOrWhiteSpace(args.Value))
{
args.IsValid = false;
_cv.ErrorMessage = "The field <strong>" + FieldName + "</strong> is required.";
return;
}
}
}
}
And it throws an exception that the DropDownList cannot have secondary controls. How come? if the TextBox allows it?
Is there any way to do this same thing without creating the composite control and rewriting the wheel? (yes, pun intended :P). I assume I could get away with creating the control and then writing it in the rendering phase AFTER the DropDownList is rendered, but I can't find out how to do it and if it's even possible (though a hack, I'm short on time on a form generator I need to finish and this is taking too long and making me feel really tired :(... you guys know I come to SO when I've used up all the resources available).
Thanks in advance! :D
Okay, I managed to do it the way I wanted, but with a bit of help from the container's page:
I had to add this to my aspx page:
<asp:PlaceHolder runat="server" ID="phValidators" />
And then here's the finished control, which adds the validator to the Page's validators placeholder I created, not the control itself:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
namespace Blah
{
public class ExtendedDropDownList : DropDownList
{
private CustomValidator _cv;
public bool Required { get; set; }
public String FieldName { get; set; }
public String ValidatorPlaceHolder { get; set; }
protected override void OnInit(EventArgs e)
{
_cv = new CustomValidator()
{
ControlToValidate = ID,
EnableClientScript = false,
ValidationGroup = ValidationGroup,
Display = ValidatorDisplay.None,
ValidateEmptyText = true
};
_cv.ServerValidate += new ServerValidateEventHandler(_cv_ServerValidate);
if (Parent.FindControl(ValidatorPlaceHolder) != null)
Parent.FindControl(ValidatorPlaceHolder).Controls.Add(_cv);
else
throw new Exception("Cannot find asp:PlaceHolder inside parent with ID '" + ValidatorPlaceHolder + "'");
base.OnInit(e);
}
private void _cv_ServerValidate(object source, ServerValidateEventArgs args)
{
if (Required && String.IsNullOrWhiteSpace(args.Value))
{
args.IsValid = false;
_cv.ErrorMessage = "The field <strong>" + FieldName + "</strong> is required.";
return;
}
}
}
}
I hope this helps someone out :)
I currently have a gridview that is populated via database through a c# method.
I wanted to know if there was a way to select the row when clicked anywhere on the row and not use the select button altogether. And then have the information from that row be sent back and populate another area on the webpage.
Is there a grid better than gridview for this? Should I outsource to jQuery? Or is gridview all I should need?
what you need to do is develop a row-clickable GridView. Best bet is to follow the instructions in the link. If your okay with VB, you can go along that route. A user has also converted it into C#, its in the comments section. Ill include it incase you dont see it.
Heres a link I have saved: http://aspadvice.com/blogs/joteke/archive/2006/01/07/14576.aspx
using System;
using System.ComponentModel;
using System.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomGridView
{
/// <summary>
/// Summary description for ClickableGridView
/// </summary>
public class ClickableGridView : GridView
{
public string RowCssClass
{
get
{
string rowClass = (string)ViewState["rowClass"];
if (!string.IsNullOrEmpty(rowClass))
return rowClass;
else
return string.Empty;
}
set
{
ViewState["rowClass"] = value;
}
}
public string HoverRowCssClass
{
get
{
string hoverRowClass = (string)ViewState["hoverRowClass"];
if (!string.IsNullOrEmpty(hoverRowClass))
return hoverRowClass;
else
return string.Empty;
}
set
{
ViewState["hoverRowClass"] = value;
}
}
private static readonly object RowClickedEventKey = new object();
public event GridViewRowClicked RowClicked;
protected virtual void OnRowClicked(GridViewRowClickedEventArgs e)
{
if (RowClicked != null)
RowClicked(this, e);
}
protected override void RaisePostBackEvent(string eventArgument)
{
if (eventArgument.StartsWith("rc"))
{
int index = Int32.Parse(eventArgument.Substring(2));
GridViewRowClickedEventArgs args = new GridViewRowClickedEventArgs(Rows[index]);
OnRowClicked(args);
}
else
base.RaisePostBackEvent(eventArgument);
}
protected override void PrepareControlHierarchy()
{
base.PrepareControlHierarchy();
for (int i = 0; i < Rows.Count; i++)
{
string argsData = "rc" + Rows[i].RowIndex.ToString();
Rows[i].Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(this, argsData));
if (RowCssClass != string.Empty)
Rows[i].Attributes.Add("onmouseout", "this.className='" + RowCssClass + "';");
if (HoverRowCssClass != string.Empty)
Rows[i].Attributes.Add("onmouseover", "this.className='" + HoverRowCssClass + "';");
}
}
}
public class GridViewRowClickedEventArgs : EventArgs
{
private GridViewRow _row;
public GridViewRowClickedEventArgs(GridViewRow aRow)
: base()
{
_row = aRow;
}
public GridViewRow Row
{
get
{ return _row; }
}
}
public delegate void GridViewRowClicked(object sender, GridViewRowClickedEventArgs args);
}
The Controls collection cannot be modified because the control contains code blocks (i.e. <% … %> ) when adding the controls dynamically having Masterpages
I am trying to add an HiddenField control to the aspx page. I am getting the below mentioned error
The Controls collection cannot be modified because the control contains code blocks (i.e. <% … %> ).
This happens when I have to add the controls dynamically. On the net, I found all the types of answers to add <%# instead of <%=. In my case this is not applicable at all.
Here is my code sample,
HiddenField hndGuid = new HiddenField();
_page.Form.Controls.Add(hndGuid);
any pointers?
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;
namespace wwwroot.Common
{
public class GuidClass
{
public GuidClass()
{
//
// TODO: Add constructor logic here
//
}
private string guid;
public string Guid
{
get
{
return guid;
}
set
{
guid = value;
}
}
}
public class Myhandler : System.Web.UI.Page, IHttpModule
{
Page _page = null;
HiddenField hndGuid = null;
Queue<string> temp;
public Myhandler()
{
temp=new Queue<string>();
}
public new void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
System.Web.HttpContext _httpContext = System.Web.HttpContext.Current;
if (_httpContext != null)
{
_page = _httpContext.Handler as System.Web.UI.Page;
if (_page != null)
{
_page.Init += new EventHandler(_page_Init);
_page.Load += new EventHandler(_page_Load);
hndGuid = new HiddenField();
hndGuid.ID = "hndGuid";
}
else
{
return;
}
}
else
{
return;
}
}
void _page_Init(object sender, EventArgs e)
{
_page.Form.Controls.Add(hndGuid);
if (!_page.IsPostBack)
hndGuid.Value = Guid.NewGuid().ToString();
}
void _page_Load(object sender, EventArgs e)
{
GuidClass currentGuid =new GuidClass();
currentGuid.Guid = hndGuid.Value;
System.Web.HttpContext _httpContext = System.Web.HttpContext.Current;
if (temp.Contains<string>(currentGuid.Guid))
{
_httpContext.Items.Add("IsRefresh",true);
}
else
{
if(!(currentGuid.Guid.Equals(null)||currentGuid.Guid.Equals("")))
temp.Enqueue(currentGuid.Guid);
_httpContext.Items.Add("IsRefresh",false);
}
}
}
}
move the code blocks into a separate user control, no code behind required
http://csharpin.blogspot.com/2011/05/about-the-controls-collection-cannot-be.html
Hi
I have succesfully made a custom ajax toolkit with a few buttoms in the footer toolbar as I wish. Now I also want to avoid crtl-v and right-click paste, but have searched, searched and tried everything with no result ... Maybe someone can lead me on the right track, I hope :)
Here below is my code (used with c# on asp.net web pages) which makes a editor control. The first part works, but the last part with the keydown is not working and maybe completely wrong?
Best regards,
Lars, Denmark
My Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Windows.Forms;
using AjaxControlToolkit.HTMLEditor;
/// <summary>
/// Særlig editor tilrettet behovet hos Boost Company
/// </summary>
namespace AjaxControlToolkit.HTMLEditor.BoostToolbarButton
{
public class Bold : AjaxControlToolkit.HTMLEditor.ToolbarButton.Bold
{
public override string ToolTip
{
get { return "Fed"; }
}
}
public class Italic : AjaxControlToolkit.HTMLEditor.ToolbarButton.Italic
{
public override string ToolTip
{
get { return "Kursiv"; }
}
}
public class Cut : AjaxControlToolkit.HTMLEditor.ToolbarButton.Cut
{
public override string ToolTip
{
get { return "Klip"; }
}
}
public class Copy : AjaxControlToolkit.HTMLEditor.ToolbarButton.Copy
{
public override string ToolTip
{
get { return "Kopier"; }
}
}
public class PasteText : AjaxControlToolkit.HTMLEditor.ToolbarButton.PasteText
{
public override string ToolTip
{
get { return "Indsæt"; }
}
}
public class InsertLink : AjaxControlToolkit.HTMLEditor.ToolbarButton.InsertLink
{
public override string ToolTip
{
get { return "Indsæt/ret link"; }
}
}
}
namespace BoostKontroller
{
public class BoostEditor : Editor
{
protected override void FillTopToolbar()
{
TopToolbar.Buttons.Add(new AjaxControlToolkit.HTMLEditor.BoostToolbarButton.Bold());
TopToolbar.Buttons.Add(new AjaxControlToolkit.HTMLEditor.BoostToolbarButton.Italic());
TopToolbar.Buttons.Add(new AjaxControlToolkit.HTMLEditor.BoostToolbarButton.Cut());
TopToolbar.Buttons.Add(new AjaxControlToolkit.HTMLEditor.BoostToolbarButton.Copy());
TopToolbar.Buttons.Add(new AjaxControlToolkit.HTMLEditor.BoostToolbarButton.PasteText());
TopToolbar.Buttons.Add(new AjaxControlToolkit.HTMLEditor.BoostToolbarButton.InsertLink());
}
protected override void FillBottomToolbar()
{
}
void OnKeyDown(KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
Clipboard.SetText(string .Empty); ;
}
}
}
}
You can do that:
$find(sControlId).get_editPanel().get_activePanel()._doc.body.onpaste =
function onPasteFunction()
{
$find(sControlId).get_editPanel().get_activePanel()._paste(false, false);
return false;
}
_paste(false, false); is to paste with plain text if you want the word paste the function is _paste(true, true);
sControlId is the client id of the editor.