is there any way to access parent page ViewState from the user control.
Yes you can ... To do so you just need to follow a basic trick ..
First inherit the caller page by a base page (using a base page over the project always a good practice it help later very much) like below ...
public abstract class BasePage : Page
{
public StateBag ViewState
{
get
{
return base.ViewState;
}
}
}
Later you can call this property from usercontrol ........
var CallerPage = this.Page as BasePage;
if (CallerPage!=null)
{
var CallerPageViewState = CallerPage.ViewState;
//Do your rest job
}
The ViewState property of the Page class is protected. Therefore, there's no way to access it from a user control, unless you're willing to break encapsulation by using reflection.
In a word no. Depending on what you want to do though there may be another way to do what you're trying to achieve
More information on what you're wanting to achieve will help people to answer your question more fully
Related
I have a master page with a user control added. The user control has properties, price and exchange rate.
I can get the control from a normal page by using master.findcontrol but it sees it as just a normal user control, so i cant get access to the controls properties, price or exchange rates.
Is there a way to solve this?
Thanks to all who view
Why not expose your custom control as a property of the masterpage. Then you can reference it like:
Master.YourCustomControl.YourCustomProperty
You have to cast the control to your custom control in order to access the properties of your custom control,
var control = (YourCustomControl)Master.FindControl("YourCustomControl");
I guess you have not exposed any properties for your custom control, Try the following,
public partial class YourControl: System.Web.UI.UserControl
{
public string textboxtext{
get { return tb_Textbox.Text ;}
set { tb_Texbox.Text = value; }
}
}
Once you create properties for all the customizable properties for your custom control, you then can access or modify them.
I'm working with dynamic fields in ASP.NET due to a very specifc and rigid end-user requirement that would take 2 hours just to explain. Suffice it to say, I can't make the requirement go away.
Anyway, I have a working solution in place; no problems with controls loading, rendering or maintaining their ViewState. This is what my OnLoad looks like:
public void override OnLoad(EventArgs e){
//don't need to check IsPostback, we have to load the controls on every POST
FormDefinition initialFormDefinition = ServiceLayer.GetFormDefinition(id);
BuildControls(initialFormDefinition);
}
In order to implement some biz logic around which dynamic fields are required, disabled or optional, I need to get the posted values (i.e. the ViewState) of my dynamic controls before I can actually add them to the page control hierarchy.
It's sort of a chicken/egg problem I suppose. ASP.NET won't automagically associate ViewState with the proper dynamic control until I've added them all to the page. On the other hand, I can't add these controls to the page until my service layer has applied biz rules that hinge on their current values. I tried to get around this rather unpleasant problem by writing this bit of pseudo-code :
public void override OnLoad(EventArgs e){
FormDefinition initialFormDefinition = ServiceLayer.GetFormDefinition(id);
BuildControls(initialFormDefinition);
if (IsPostBack){
PushControlValuesIntoForm(initialFormDefinition);
var updatedFormDefinition = ServiceLayer.ApplyBizRules(initialFormDefinition);
ReBuildControls(updatedFormDefinition); //remove controls and re-add them
}
}
Unfortunately, when you clear a control and re-add it, the ViewState is lost, even if the control type and ControlID are exactly the same, so this solution is a bust. Any reasonable ideas on how to accomplish what I'm after are welcome!
One way could be to load your controls and then decide if you need form definition to be be updated and if yes then re-initiate page life cycle again. See the below sample code:
public void override OnLoad(EventArgs e){
var updatedFormDef = Context.Items["UpdatedDef"] as FormDefinition;
if (null != updatedFormDef)
{
// Updated form def, rebuild controls
BuildControls(updatedFormDef);
}
else
{
// load initial form def
var initialFormDefinition = ServiceLayer.GetFormDefinition(id);
BuildControls(initialFormDefinition);
// check whether we need to update form def
if (IsPostBack){
PushControlValuesIntoForm(initialFormDefinition);
var updatedFormDefinition = ServiceLayer.ApplyBizRules(initialFormDefinition);
if (null != updatedFormDefinition)
{
// we have to update UI, transfer to self
Context.Items["UpdatedDef"] = updatedFormDefinition;
try
{
Server.Transfer(this.Request.RawUrl, true);
}
catch(ThreadAbortException)
{
// Do nothing
}
}
}
}
I want to make a custom ASP.NET control that is a subclasse of System.Web.UI.WebControls.Calendar. I need it to add a few data members and set up a few event handlers in it's constructor.
Is this possible? If so How?
So far I have tried using add new item to add a default web user control and tried editing in Calendar in a few different places. None have worked so far.
Edit: it seems I'm totally missing how this stuff is supposed to work.
Does anyone known of a demo project that I can look at? Something that already exists. (Unless you are really board, don't go out and make one for me.)
Unless I'm misunderstanding the question, you can just create a new class file and inherit from Calendar. Add in the properties you need, and the event handlers you want to set up.
public class MyCalendar : System.Web.UI.WebControls.Calendar
{
public MyCalendar()
{
// set up handlers/properties
}
}
Then anywhere you'd like to add a Calendar to your pages, you can simply create a MyCalendar instead. If you need to do so in the designer, you can look at several good tutorials about how to make your inherited controls show their new properties in the designer, like this one.
In a new class file you need to inherit from System.Web.UI.WebControls.Calendar instead of System.Web.UI.UserControl.
namespace MyNamespace
{
[ToolboxData("<{0}:UserCalendar runat=\"server\" />")]
public class UserCalendar : System.Web.UI.WebControls.Calendar
{
private string property1;
public UserCalendar() { }
public string Property1 { get { return property1;} set { property1 = value; } }
}
}
Then on your .aspx page (or in another control .ascx):
<%# Register TagPrefix="userControl" namespace="MyNamespace" assembly="MyProjectAssembly" %>
<userControl:UserCalendar runat="server" ID="myCalendar" property1="some value" />
Stuff to read: Developing Custom ASP.NET Server Controls.
If I create a user control (EDIT:not a web control/server control) it's pretty trivial to get databinding. I just add a datasourceID property.
In code behind (vb)
Partial Public Class BandedControl
Inherits UserControl
Public Property DataSourceID() As String
Get
Return MyGridView.DataSourceID
End Get
Set(ByVal value As String)
MyGridView.DataSourceID = value
End Set
End Property
End Class
In code behind (c#)
public partial class BandedControl : UserControl
{
public string DataSourceID {
get { return MyGridView.DataSourceID; }
set { MyGridView.DataSourceID = value; }
}
}
My issue is that this breaks design time rendering and also I don't get a drop down list to choose my datasource. How do I resolve this. (Hint: I think I need a type convertor, but all the info I can find relates to server controls not user controls).
You could try adding the IDReferenceProperty attribute to your property definition...
public partial class BandedControl : UserControl
{
[System.Web.UI.IDReferenceProperty(typeof(DataSourceControl))]
public string DataSourceID
{
get
{
return MyGridView.DataSourceID;
}
set
{
MyGridView.DataSourceID = value;
}
}
}
See http://msdn.microsoft.com/en-us/library/system.web.ui.idreferencepropertyattribute.aspx for more info about the IDReferencePropertyAttribute class.
If that doesn't work - I'd also try to inherit from DataBoundControl instead of UserControl and see if that gets you anywhere.
Web UserControls are compiled dynamically at run time and so are not rendered at Design time, what you want to do is create a Web Custom Control. Your best bet here is to extend one of the existing Bindable Web Controls
http://msdn.microsoft.com/en-us/library/aa651710(VS.71).aspx
Not sure if this is exactly what you want but I seem to remember them showing something similar to this in some dnr tv episodes.
I think it was Miguel Castro episodes 1 & 2, but it could be episode 31.
An archive of all the videos is here
I know that in the next version of ASP.NET we'll finally be able to set the clientids on System.Web controls without the framework doing it for us in a quasi-intelligent way e.g:
id="ctl00__loginStatus__profileButton"
Does anyone know a good method in the meantime to force the above id to something like
id="profileButton"
The main reason for this is manipulation of the clientids in jQuery when dynamically adding controls to a page. The problem I can see is changing the ids will break the Viewstate?
You have to use the ClientIDMode attribute:
<asp:xxxx ID="fileselect" runat="server" ClientIDMode="Static"/>
What I tend to do is dynamically generate javascript methods which handle this. You can do this in markup or code behind so for example:
<script language="javascript" type="text/javascript">
function doXYZ()
{
$("#" + getListBoxId()).css(...)
}
function getListBoxId()
{
return "<%=this.myListBox.ClientId>";
}
</script>
You can also build the functions in the code behind and register them.
EDIT
A couple months ago I needed to fix the id of some server controls, I managed to hack it in and I described my method here here.
Basically you need put the controls inside a naming container like a user control, and then override a couple of properties which prevents the child controls from getting their uniqueid.
The performance isn't great, but you can use this selector syntax to match messy ClientIDs:
$("[id$='_profileButton']")
That matches any element ending in _profileButton. Adding the leading underscore ensures that you're matching the desired element and not another element that ends in the substring "profileButton" (e.g. "myprofileButton").
Since it has to iterate over the entire DOM, the performance can be poor if you use it in a loop or several times at once. If you don't overuse it, the performance impact is not very significant.
Another way would be to wrap your control with a div or span with a static id, then access the control through that.
E.g.
<span id="mySpan">
<asp:TextBox id="txtTest" runat="server" />
</span>
You could then target input tags inside MySpan. (though I agree it would be nice to be able to specify a nice name, provided you could handle the naming conflicts...)
I have often run in to this "problem" while developing in asp.net webforms. In most cases I tend to use the css class of the element.
jQuery(".My .Container12")
Before starting to manipulate the id:s, perhaps that is a way you can handle it aswell? It's a simple solution.
There is another solution not mentioned which is to subclass the ASP.NET controls and force the IDs:
public class MyCheckBox : CheckBox
{
public string ForcedId { get;set; }
public override string ID
{
get
{
if (!string.IsNullOrEmpty(ForcedId))
return ForcedId;
else
return base.ID;
}
set
{
base.ID = value;
}
}
public override string ClientID
{
get
{
return ID;
}
}
}
Then use this where you know the IDs will never clash:
<mytag:MyCheckBox ForcedId="_myCheckbox" runat="server" />
If you are using lists you will need to write a ListControlAdapter, and also adapters for each type of list you're using (dropdown,checkbox,radiobutton,listbox). Alternatively cross your legs and wait for .NET 4.0.