I have a server-side control which renders as <input type="Something"> or <textarea>. The code is self-explanatory:
public string Namespace
{
get { return nspace; }
set { nspace = value; }
}
public string Model
{
get { return model; }
set { model = value; }
}
public string Text
{
get { return text; }
set { text = value; }
}
public string TextMode
{
get { return textMode; }
set { textMode = value; }
}
public string _Type
{
get { return type; }
set { type = value; }
}
public string Property { get; set; }
protected override void RenderContents(HtmlTextWriter output)
{
output.AddAttribute(HtmlTextWriterAttribute.Id, Property.ToLower());
output.AddAttribute(HtmlTextWriterAttribute.Name, Property.ToLower());
output.AddAttribute(HtmlTextWriterAttribute.Type, _Type);
if(!String.IsNullOrEmpty(Text))
output.AddAttribute(HtmlTextWriterAttribute.Value, Text);
Type modelType = Type.GetType(string.Format("{0}.{1}", Namespace, Model));
PropertyInfo propInfo = modelType.GetProperty(Property);
var attr = propInfo.GetCustomAttribute<RequiredAttribute>(false);
if (attr != null)
{
output.AddAttribute("data-val", "true");
output.AddAttribute("data-val-required", attr.ErrorMessage);
}
//forces styles to be added to the control
this.AddAttributesToRender(output);
if (!String.IsNullOrEmpty(TextMode))
{
output.RenderBeginTag("textarea");
output.RenderEndTag();
}
else
{
output.RenderBeginTag("input");
output.RenderEndTag();
}
}
This control is aimed at getting validation error messages from Data Model (instead of providing "data-val" and "data-val-required" to every textbox).
using this code is easy:
<ServerControlTag:ControlName Property="aProp" runat="Server" Model="MyModel" ID="txtSomething" />
Which renders as a input type=text tag, and the following renders as a textarea tag:
<ServerControlTag:ControlName Property="Description" runat="Server" Model="MyModel" TextMode="MultiLine" ID="txtDescription" class="message" />
My problem is when rendering textarea I cannot find any attribute to fill the text of textarrea. To set text in a textarea I have just found the following syntax:
<textarea ... > My Text Here </textarea>
yet, I don't know how to implement it in my server control. I don't know even if I am on the right track.
You need to call the normal Write() method to write text inside the tag.
Remember to HTML-encode the text.
Related
public partial class ChatUserControl : System.Web.UI.UserControl
{
UserChatClass ucc = new UserChatClass();
public ChatUserControl()
{
lblChatFriend = new Label();
txtChatMessage = new TextBox();
imgFriend = new Image();
rpChatMessages = new Repeater();
}
public string ChatFriend { get { return this.lblChatFriend.Text; } set { this.lblChatFriend.Text = value; } }
public string imgFriendUrl { get { return this.imgFriend.ImageUrl; } set { this.imgFriend.ImageUrl = value; } }
public object rpChatDataSource { get { return this.rpChatMessages.DataSource; } set { this.rpChatMessages.DataSource = value; } }
public Repeater rpChatMessagesToBind { get { return this.rpChatMessages; } set { this.rpChatMessages = value; } }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ChatUserControl user1 = new ChatUserControl();
divChatUserControlCover.Controls.Add(user1);
}
}
private void BindUserControls()
{ ChatUserControl user1 = divChatUserControlCover.Controls[1] as ChatUserControl;
user1.ChatFriend = row["username"].ToString();
user1.imgFriendUrl = "../../HttpImageHandler.jpg?username=" + row["username"].ToString();
DataSet dsCM = ucc.GetChatMessages(Session["username"].ToString(), row["username"].ToString());
user1.rpChatDataSource = dsCM;
user1.DataBindForRpChatMessagesToBind();
user1.Visible = true;
}
Master.aspx
<div id="divChatUserControlCover" runat="server">
</div>
Ok I have edited the code and now I have created properties. How do I call the DataBind method for rpChatMessages? I also cant see my usercontrol on page. Why
I'm not sure if your trying to reference the first label or second label. If its the second lable you can't just do chatMessage. you would have to do
((Label)rpChatMessages.FindControl("chatMessage")) due to scope of controls.
When you reference a component inside another component (ie Repeater) the child component no longer belongs to the document (implied this) but rather belongs to the control, ie
this.rpChatMessages { chatMessage }
I think you are just trying to pass a value to one control inside a UserControl if this is correct, declare a public property like this:
ASCX code behind
public string MyProperty
{
get
{
return this.lbl.Text;
}
set
{
this.lbl.Text = value;
}
}
Setting the value to the UserControl
private void BindUserControls()
{
ChatUserControl user1 = divChatUserControlCover.Controls[1] as ChatUserControl;
user1.MyProperty = row["username"].ToString();
Setting the value in the page markup
<uc1:ChatUserControl MyProperty='<%# Eval("some field") %>' ...
Edit 1
Remove that line
public object rpChatDataSource { get { return this.rpChatMessages.DataSource; } set { this.rpChatMessages.DataSource = value; }
And instead add a method
public void BindMyRepeaterOrWhatever(IEnumerable<Yourentity> data)
{
this.myDataBoundControl.DataSource = data;
this.myDataBoundControl.DataBind();
}
You can change the IEnumerable<Yourentity> data for object data but if you can pass a strongly typed enumeration would be better
To my surprise I found why my user control's child controls dont get instantiated. Its because ChatUserControl user1 = new ChatUserControl() doesnt get its child controls initialized.
The proper way to create a new intance of user control is this way....
ChatUserControl user1 = (ChatUserControl)Page.LoadControl("~/ChatUserControl.ascx");
Is it possible to bind properties on the client and server side in Scriptcontrol, so when I set property in javascript, change will be visible also in code behind and when I set property in code behind, change will be visible in javascript?
I can't get it work like above - it is set initially, when I set property where scriptcontrol is declared, but when I change it later it is still the same as before...
EDIT: I try to do a ProgressBar for long postbacks in our ASP.NET application. I have tried many options but none works for me... I want to set progress value in code behind and has it updated in view during long task postback.
Code for ScriptControl:
C#:
public class ProgressBar : ScriptControl
{
private const string ProgressBarType = "ProgressBarNamespace.ProgressBar";
public int Value { get; set; }
public int Maximum { get; set; }
protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
this.Value = 100;
this.Maximum = 90;
var descriptor = new ScriptControlDescriptor(ProgressBarType, this.ClientID);
descriptor.AddProperty("value", this.Value);
descriptor.AddProperty("maximum", this.Maximum);
yield return descriptor;
}
protected override IEnumerable<ScriptReference> GetScriptReferences()
{
yield return new ScriptReference("ProgressBar.cs.js");
}
}
Javascript:
Type.registerNamespace("ProgressBarNamespace");
ProgressBarNamespace.ProgressBar = function(element) {
ProgressBarNamespace.ProgressBar.initializeBase(this, [element]);
this._value = 0;
this._maximum = 100;
};
ProgressBarNamespace.ProgressBar.prototype = {
initialize: function () {
ProgressBarNamespace.ProgressBar.callBaseMethod(this, "initialize");
this._element.Value = this._value;
this._element.Maximum = this._maximum;
this._element.show = function () {
alert(this.Value);
};
},
dispose: function () {
ProgressBarNamespace.ProgressBar.callBaseMethod(this, "dispose");
},
get_value: function () {
return this._value;
},
set_value: function (value) {
if (this._value !== value) {
this._value = value;
this.raisePropertyChanged("value");
}
},
get_maximum: function () {
return this._maximum;
},
set_maximum: function (value) {
if (this._maximum !== value) {
this._maximum = value;
this.raisePropertyChanged("maximum");
}
}
};
ProgressBarNamespace.ProgressBar.registerClass("ProgressBarNamespace.ProgressBar", Sys.UI.Control);
if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
I'll appreciate any way to implement this progress bar...
Personally, I do this often using hidden fields.
Bear in mind that hidden fields are not secure and may have other downfalls, since they don't actually hide their value, just simply do not display it.
ASPX Markup
<asp:HiddenField ID="hiddenRequest" runat="server" ClientIDMode="Static" />
ASPX.CS Code behind
public string HiddenRequest
{
set
{
hiddenRequest.Value = value;
}
get
{
return hiddenRequest.Value;
}
}
Page JAVASCRIPT (with jQuery)
$('#hiddenRequest').val('MyResult');
This way, I can access the same field using one variable as such, accessed both from client side and server side.
I have a custom asp-net control that inherits from another one and its works as expected, though the properties are only set properly if i code them in the markup directly, so for instance if i need set a property at runtime that is some dynamic value, this value is never set or somehow lost.
Here's the markup code:
<!--related form-->
<fw:advancedformdisplay id="formDisp" runat="server" captchaenabled="true" EmailEnabled="true" EnableViewState="true" captchaprivatekey="xxxxxxxxxxxxxxxxxxxx" captchapublickey="xxxxxxxxxxxxx" captchatheme="white" SourceType="MenuItem" SourceMainId="Auto">
</fw:advancedformdisplay>
This is the code of the control:
[DefaultProperty("CaptchaEnabled"),ToolboxData("<{0}:AdvancedFormDisplay runat=server></{0}:AdvancedFormDisplay>"), Description("This is an enhanced FormDisplay control that inlcudes Googles Captcha control is enabled")]
public class AdvancedFormDisplay :SiteBuilder.WebControls.FormDisplay
{
bool _CaptchaEnabled = false, sendEmail = false;
string captchaErrorMessage = "The verification code entered is not valid. Please try again!";
RecaptchaControl captchaControl = null;
string captchaPrivateKey = "", captchaPublicKey = "", captchaTheme = "clean";
string originalFormHtml = string.Empty;
string afterText = string.Empty, beforeText = string.Empty;
Literal litHtmlForm = null;
string captchaErrorClass = "errorCaptcha";
public string EmailBeforeText
{
get { return beforeText; }
set { beforeText = value; }
}
public string EmailAfterText
{
get { return afterText; }
set { afterText = value; }
}
public string CaptchaErrorClass
{
get { return captchaErrorClass; }
set { captchaErrorClass = value; }
}
public bool CaptchaEnabled
{
get { return _CaptchaEnabled; }
set { _CaptchaEnabled = value; }
}
public bool EmailEnabled
{
get { return sendEmail; }
set { sendEmail = value; }
}
public string CaptchaErrorMessage
{
get { return captchaErrorMessage; }
set { captchaErrorMessage = value; }
}
/// <summary>
/// red,white,blackglass,clean
/// </summary>
public string CaptchaTheme
{
get { return captchaTheme; }
set { captchaTheme = value; }
}
public string CaptchaPrivateKey
{
get { return captchaPrivateKey; }
set { captchaPrivateKey = value; }
}
public string CaptchaPublicKey
{
get { return captchaPublicKey; }
set { captchaPublicKey = value; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
public override void OnSaved(FormDisplayEventArgs e)
{
//If captcha control is enabled we need to adda bit of code to redirect form properly
if (CaptchaEnabled && e.Redirect && !e.SendMail)
{
//Do Stuff
}
if(sendEmail)
{
//Send email
}
base.OnSaved(e);
}
public override void OnSaving(FormDisplayEventArgs e)
{
if (CaptchaEnabled)
{
//Validate and do stuff
}
base.OnSaving(e);
}
}
And then in my asp.net page that is using control, created by markup code, in the Page_Load() i try to assign some values to some properties and and the values aren't set properly, meaning that if i have set for isntance, the property EmailBeforeText = "somthing" this value will not be assigned..
protected void Page_Load(object sender, EventArgs e)
{
//2: Get the language of menuitem - Based on current culture setting (for by dropdownbox - change logic)
try
{
currentCulture = Thread.CurrentThread.CurrentCulture.ToString();
// Redirect if domain does not match rootnode.
DomainChecker.CheckURL(this.Request, this.Response, currentCulture);
if (footerArticle != null)
footerArticle.SourceMenuId = Digimaker.Config.Custom.Get("FooterID_" + currentCulture).ToString();
}
catch
{
currentCulture = "en-GB";
if( footerArticle != null )
footerArticle.SourceMenuId = Digimaker.Config.Custom.Get("FooterID_" + currentCulture).ToString();
}
Any ideas what i'm missing here?
Thanks a lot for your reading!
Regards,
byte_slave
short answer: use viewstate to persist your custom values!
Understanding ASP.NET ViewState whitepaper (see example with NavigateUrl)
edit: as reading the white-paper is obviously a really hard thing:
Each control is responsible for storing its own state, which is
accomplished by adding its changed state to its ViewState property.
The ViewState property is defined in the System.Web.UI.Control class,
meaning that all ASP.NET server controls have this property available.
(When talking about view state in general I'll use lower case letters
with a space between view and state; when discussing the ViewState
property, I'll use the correct casing and code-formatted text.)
If you examine the simple properties of any ASP.NET server control
you'll see that the properties read and write directly to the view
state. (You can view the decompiled source code for a .NET assembly by
using a tool like Reflector.) For example, consider the HyperLink Web
control's NavigateUrl property. The code for this property looks like
so:
public string NavigateUrl
{
get
{
string text = (string) ViewState["NavigateUrl"];
if (text != null)
return text;
else
return string.Empty;
}
set
{
ViewState["NavigateUrl"] = value;
}
}
As this code sample illustrates, whenever a control's property is
read, the control's ViewState is consulted. If there is not an entry
in the ViewState, then the default value for the property is returned.
When the property is assigned, the assigned value is written directly
to the ViewState.
I have written the following override for the DataFormatString in my BoundField derived control, yet the field is still formatted as a plain number. I assume that this is because the formatting code isn't calling the DataFormatString property but using the private _dataField field. I would like set the base property in my override, but I want to do so based on a declarative FormatType enum property that will determine which default format string to use. Where could I do this?
public override string DataFormatString
{
get
{
var baseString = base.DataFormatString;
if (!string.IsNullOrWhiteSpace(baseString))
{
return FormatStrings.Currency;
}
return baseString;
}
set
{
base.DataFormatString = value;
}
}
EDIT: It turns out declarative property values are set when the control is built by it's parent, so it's pretty safe to assume they won't be properly used until after this phase of the page life cycle. This is what I actually wanted to know.
You can add the DefaultValue attribute at the top of the method:
[DefaultValue(false)]
public bool SomeCondition
{
get { return someCondition; }
set { someCondition = value; }
}
It looks like the parameterless constructor is the best place to do this. I wanted to set some properties to default values based on other properties, but I realised it wasn't necessary if I determined these defaults when needed, versus in the property getters. E.g:
public BoundReportField()
{
_formatType = FieldFormatTypes.String;
}
protected virtual string GetDefaultFormatString(FieldFormatTypes formatType)
{
var prop = typeof(FormatStrings).GetProperty(formatType.ToString()).GetValue(null, null);
return prop.ToString();
}
protected virtual IFormatProvider GetFormatProvider(FieldFormatTypes formatType)
{
var info = (CultureInfo)CultureInfo.CurrentCulture.Clone();
info.NumberFormat.CurrencyDecimalDigits = 0;
info.NumberFormat.CurrencySymbol = "R";
info.NumberFormat.CurrencyGroupSeparator = ",";
info.NumberFormat.CurrencyDecimalSeparator = ".";
return info;
}
private FieldFormatTypes _formatType;
public virtual FieldFormatTypes FormatType
{
get { return _formatType; }
set
{
_formatType = value;
}
}
protected override string FormatDataValue(object dataValue, bool encode)
{
var formatString = DataFormatString;
var formatProvider = GetFormatProvider(_formatType);
if (string.IsNullOrWhiteSpace(formatString))
{
formatString = GetDefaultFormatString(_formatType);
}
ApplyFormatStyles(_fieldCell);
var retString = string.Format(formatProvider, formatString, dataValue);
return retString;
}
I have created a very simple custom control:
[assembly: System.Web.UI.TagPrefix("CustomMultiLineTextBox", "evo")]
public class CustomMultiLineTextBox :
System.Web.UI.WebControls.TextBox
{
public override int Rows
{
get
{
return 5;
}
}
public override System.Web.UI.WebControls.TextBoxMode TextMode
{
get
{
return System.Web.UI.WebControls.TextBoxMode.MultiLine;
}
}
public override string CssClass
{
get
{
return "textboxStyle";
}
set
{
//base.CssClass = "textboxStyle";
base.CssClass = value;
}
}
}
}
However, when I drop this control onto my aspx page the CssClass does not seem to be applied. The TextMode and Rows property are set correctly.
<evo:CustomMultiLineTextBox ID="txtTrainingNeeds" runat="server">
</evo:CustomMultiLineTextBox>
Only if I add CssClass="textboxStyle" to markup will the CssClass be applied.
Any suggestions?
Thanks in advance
Since it doesn't look like you're modifying behavior, only data, I would set the properties to the values you want in the constructor instead of overriding the properties themselves.
public CustomMultiLineTextBox()
{
Rows = 5;
TextBoxMode = System.Web.UI.WebControls.TextBoxMode.MultiLine;
CssClass = "textboxStyle";
}