Attach RequiredValidator on custom server control rendering a TextBox - c#

I don't know whether this is really possible, but I'm trying my best.
If I have a (complex) custom server control which (beside other controls) renders a TextBox on the UI. When placing the server control on a page, would it be possible to attach a RequiredField validator to that server control, such that the validator validates the Text property of that control which points to the Text property of the rendered TextBox?
Of course I could incorporate the RequiredField validator directly into the server control, but this is for other reasons not possible (we are rendering RequiredField validators automatically on the UI).
Thanks for your help.

I think one solution is to put your TextBox control inside a Panel then you add the RequiredValidator control dynamically on the Page_Load event handler.
<asp:Panel ID="Panel1" runat="server">
<MyCustomTextBox ID="TextBox1" runat="server"></MyCustomTextBox>
</asp:Panel>
<asp:Button ID="Button1" runat="server" Text="Button" />
then
protected void Page_Load(object sender, EventArgs e)
{
var validator = new RequiredFieldValidator();
validator.ControlToValidate = "TextBox1";
validator.ErrorMessage = "This field is required!";
Panel1.Controls.Add(validator);
}
I put the CustomTextBox inside the panel to assure that the validation controle place is correct when added

I got it, the 2nd time that I'm answering to my own post :) Next time I'll do a deeper research before.
For those of you that may encounter the same problem. You have to specify the ValidationProperty attribute on your server control's class. For instance if your server control exposes a property "Text" which is displayed to the user and which should also be validated, you add the following:
[ValidationProperty("Text")]
Then it should work.

Related

C# - How to change value of textbox on focus

I'm writing an application in C#. I would like to replace the value for the TEXT property after the user clicks (focuses) on a textbox. I would like to set the TEXT value to be blank instead of the words "ENTER NAME HERE" when they click to edit the textbox.
Front-end:
<asp:TextBox Text="ENTER NAME HERE" OnClick="MyTextboxID_OnClick" ID="MyTextboxID" runat="server"></asp:TextBox>
Code-behind:
protected void MyTextboxID_OnClick(object sender, EventArgs e)
{
MyTextboxID.Text = "";
}
I tried to find the answer to this question but the answers didn't quite match what I wanted to do.
I was hoping C# had something similar to Javascript's "OnClick" or "OnFocus" events. I added the OnClick event to the textbox for illustration purposes. This OnClick event doesn't work.
Thank you in advance for your help!
Remember that ASP.NET is primarly server-side. Actions that run in C# require a post-back to the server. The impact of this on a page can be mitigated somewhat by using AJAX, but this is why you don't see an "OnClick" event off the ASP control.
However, you can still use the Javascript "OnClick" event. Since Javascript runs on the client, and the interaction in this instance is entirely handled on the client, you should just use that.
If you are not comfortable using Javascript, you might want to look at TextBoxWatermark server side control.
It is available NuGet.
<asp:TextBox OnClick="MyTextboxID_OnClick"
ID="MyTextboxID" runat="server">
</asp:TextBox>
<ajaxToolkit:TextBoxWatermarkExtender ID="TBWE2" runat="server"
TargetControlID="MyTextboxID"
WatermarkText="ENTER NAME HERE"
WatermarkCssClass="watermarked" />
You should simply use the following Placeholder="Enter text here."
Option One:
<asp:Textbox id="txtName" runat="server" placeholder="Enter name here." />
Option Two:
$("#<%= txtName.ClientId %>").setAttribute('placeholder', 'Enter name here.');
$("#<%= txtName.ClientId %>").attr('placeholder', 'Enter name here.');
For the Javascript implementation, you would simply place that in your View and wrap it in: <script type="text/javascript"></script>. Those are the ideal approaches to display text which clears on focus.
You could also utilize the Tooltip. Hopefully these examples assist you. Important note, I have no issues with compatibility in IE 8 with the Placeholder. Also these approaches won't force a Postback which can occur due to Server-Side. Which would force you to either do a Postback or implement a Update Panel / Ajax to hide the Postback.
Plugin: https://github.com/mathiasbynens/jquery-placeholder
Why don't you use the place holder attribute and not have to worry about replacing the text at all. This would show when the text box is empty but disappear on focus

How to place a declared panel in a declared placeholder in code behind?

I have an aspx page with different placeholders and different asp panels declared in the page. In certain conditions I would like to display certain panels inside certain placeholders. I know how to do this in Javascript and I know how to add a programatically created control in a placeholder's controls collection. However my panels and placeholders are already declared in the page.
I was wondering if there's a way to put an already declared panel in a placeholder in code behind?
However my panels and placeholders are already declared in the page.
Yes, you can relocate Panel1 located inside PlaceHolder1 to PlaceHolder2. However, it is not common to relocate controls which are already declared in aspx page.
<asp:PlaceHolder runat="server" ID="PlaceHolder1">
<asp:Panel runat="server" ID="Panel1">
<h1>Panel 1</h1>
</asp:Panel>
</asp:PlaceHolder>
<asp:PlaceHolder runat="server" ID="PlaceHolder2">
<asp:Panel runat="server" ID="Panel2">
<h1>Panel 2</h1>
</asp:Panel>
</asp:PlaceHolder>
PlaceHolder1.Controls.Add(Panel2);
PlaceHolder2.Controls.Add(Panel1);
There are following alternative method you might want to consider -
Method 1
Show and hide panels based on your logic. For example, SomePanel.Visible = true|false;
Note: Ideally, you do not want to add a lot of controls to a page; the reason is ViewState will be very heavy even if they are not displayed to a user.
However, it is very easy to implement compare to other methods.
Method 2
Load UserControl to PlaceHolder dynamically.
var control = LoadControl("SomeUserControl.ascx");
YourPlaceholder.Controls.Add(control);
Method 3
Create controls dynamically. It is a lot more complicated, because you need to reload those controls on every post back.
Since the ASP.NET control hierarchy is built very early on in the page life cycle, in order to dynamically add panel controls to placeholder controls, you will have to do that in the during the Page_Init event1.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Panel pnl = new Panel();
plc.Controls.Add(pnl);
}

CustomValidator ServerValidate method does not fire

I've put a CustomValidator on my form. I have not set its ControlToValidate property. In its ServerValidate event I've written the following:
protected void CustomValidator1_ServerValidate(object source,
ServerValidateEventArgs args)
{
args.IsValid = false;
}
I put a breakpoint to this method but it seems to never come to that point. But if I do this on another form it works like a charm.
The ValidationGroup property of both the button and the CustomValidator are the same
I tried deleting this property in both the button and the CustomValidator, still does not work.
It seems as there's something formwide. I just put a CustomValidator on the form and do not touch any of its properties other than just setting its ServerValidate event method.
EDIT: Here's the aspx part:
<asp:CustomValidator ID="CustomValidator2" runat="server"
ErrorMessage="This is a test"
onservervalidate="CustomValidator1_ServerValidate"
ValidationGroup="PA"></asp:CustomValidator>
<asp:Button ID="btnPensionersOK" runat="server" Text="OK" Width="75px"
onclick="Button1_Click" ValidationGroup="PA" />
Try to force the validation in the button-click handler via Page.Validate:
protected void Button1_Click(Object sender, EventArgs e)
{
Page.Validate();
if(Page.IsValid)
{
// servervalidate should have been called
}
}
Edit(from comments):
If you want the customvalidator to validate if nothing was entered/selected in your controls, you need to set ValidateEmptyText to true. You also might want to let the CustomValidator replace the RequiredFieldValidators.
I assume that the validator-order on the aspx decides whether or not a customvalidator's severvalidate is called if a previous Validator already has made Page.IsValid=false. Or ASP.NET is so smart that it assumes the SeverValidate to be costlier than a simple text-is-empty check.
I would also like to put some more help for those who will use CustomValidators and RequiredFieldValidators at the same time. One should take into account that Client side validation takes place first. And the server side validation will occur only after PostBack. I'm sure you got it but just in case this is not quite clear: It means first all the controls that are bound to certain client side working validators must be valid to let Postback to occur. After Page. IsValid is True server side stuff takes place and posts back any changes which includes server side validation messages.
So here are the ways one can make both CustomVCalidators and other built in validators to work at the same time.:
Set both groups of validators to work on Client side. In this case we must ensure that for the custom valitor(s) we spacify the script that will make validation on the client side. Without writing script and just filling in the ServerValidate method the validation will take place in the server.Even if EnableClientScript property is set to True.
Set both groups of validators to work on server side. To do so simply set EnableClientScript to False. But note that this will load the server.

Passing parameters to a User Control

We are trying here to localize our user control basically we want to be able to do something like this :
<in:Banner runat="server" ID="banners" Lang="fr" />
The way we do this is by page level and send it to master that then send it to the control:
protected void Page_Load(object sender, EventArgs e)
{
Master.Lang = "FR";
}
Then in the MasterPage.master we do something like this :
<in:Banner runat="server" ID="banners" Lang="<%= Lang %>" />
The masterpage has a public proprety named Lang.
In the control we have set a field that contains the default language and a proprety (Lang) that set the language. It seems that whatever we do, the current language is not sent from the page to the usercontrol... any help?
Not exactly like that, but you can consider the content page like a control in the master page, so its likely that the page load of the page is executing before the page load of that user control.
Regardless of the above, why not set the ui culture to the asp.net thread (probably from the global.asax), and using that from the control.
Another alternative is to have a separate class where you hold the current language, and expose a change event ... that way you can make sure to use the right language even if the load is done differently --- or there is a change language event later.
You can access it in code-behind of the MasterPage like this
public void SetLanguage(string language)
{
banners.Lang = language; //banners is an ID reference to your user control.
}
Or in your markup I think you can do it like this
<in:Banner runat="server" ID="banners" Lang='<%# Bind("Lang") %>' />
I should mention that Bind works in .Net 2.0 and up.

Resolving viewstate/namespace conflicts

I have a listbox control. When the user clicks it, it tells a custom control to use a certain ID to use.
The custom control draws the same thing everytime(dynamically), just loads different content depending on this ID(it's loaded from a database into a dynamic form like control).
Ok, Now I'm having trouble with viewstate spillage. When you click the listbox to load say ID #1, it'll all look good. Then, you click on ID #2 and all the textbox controls created inside the custom control has the same thing that was put in ID #1. So when the listbox index changes I need to clear the view state, but I can't get this to work.
All of the controls are created at Page_Load also.
I tried ViewState.Clear() at Page_Load but that didn't do anything.
I had the custom control derive from INamingInterface, but I guess the IDs still match for viewstate.
I've tried changing the custom controls ID to something unique(like "CONROL_"+id.ToString()) I've also tried doing the same thing with the panel containing the custom control.
I can not seem to get rid of this view state!
EDIT
Ok here is code that demonstrates the problem
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (ddl.SelectedValue == "1")
{
Create("ID #1");
}
else if (ddl.SelectedValue == "2")
{
Create("ID #2");
}
}
void Create(string text)
{
TextBox t = new TextBox();
t.Text = text;
pnl.Controls.Add(t);
}
}
the markup:
<div>
<asp:Panel ID="pnl" runat="server">
<asp:DropDownList ID="ddl" runat="server" AutoPostBack="True">
<asp:ListItem Text="id 1" Value="1">
</asp:ListItem>
<asp:ListItem Text="id 2" Value="2"></asp:ListItem>
</asp:DropDownList>
</asp:Panel>
</div>
If you run this code you'll notice that if you change what is in the textbox and then you change the dropdown list, then what you typed earlier will be kept in there instead of it being overwritten..
My basic goal with this is to get it so that when you change to ID #2, it puts "ID #2" in the textbox no matter what(preferably without disabling viewstate altogether)
If I set the ID of the Text control then it doesn't retain the old value. Are you giving all controls a unique id?
void Create(string text)
{
TextBox t = new TextBox();
t.ID = text;
t.Text = text;
pnl.Controls.Add(t);
}
You can't do it that way.
For viewstate to work properly all controls must be created before it is loaded and with the same id's. So you must store the control definitions in session and recreate then with the same ids to ASP.NET load their properties from the view state. Page_load is too late, do it at PreLoad.
But it is easier to have all controls created at design time with visible set to false, and alternate their visibility so viewstate will work properly.
Actually this is no longer relevant. We fixed it by just disabling viewstate for our dynamically created controls. This would not work in all instances, but in our case there are two buttons the user can push(that are to do with the dynamic controls) or a list box to switch forms. The two buttons both save the state of the controls to database, so viewstate is not actually needed.(I always get confused when thinking about viewstate and how it interacts with controls.. )
So basic advice: If your having trouble controlling the viewstate, be sure you actually need it.

Categories