I'm building a Custom Control which simply inherits from RegularExpressionValidator. In the constructor I need to be able to see what the viewstate value of the control is so that I can use that value during the construction to determine which validation expression I need it to use.
The problem is the constructor does not have access to viewstate when it is called. At least viewstate is always null due to the timing when the constructor is called.
I have tried overriding the render method, but for some reason, even though the control has access to the viewstate the base.validationexpression always fails due to it not being assigned in the constructor.
What I have is a public property that looks at the viewstate.
public NameType NameValidationType
{
get
{
return this.ViewState["NameType"] == null ? NameType.FirstName : (NameType)ViewState["NameType"];
}
set
{
this.ViewState["NameType"] = value;
}
}
This value is always null when the constructor is called. Is there some way to delay the execution of the constructor to read from viewstate before being constructed?
Thanks for any help.
My solution to get this to work is to build the controls base validationexpression and other attributes in the OnPreRender event. Render was too late and anything before the OnPreRender did not have access to viewstate.
Related
I have a property, of a custom class, in C# that I have overridden the setter for. I want to compare a property of/in the custom class in the setter, like the following:
public DatabaseInfo CurrentDatabaseManagedSelection
{
get { return CurrentDatabaseManaged; }
set {
if (String.Equals(value.Name, CurrentDatabaseManaged.Name,StringComparison.OrdinalIgnoreCase))
return;
CurrentDatabaseManaged = DatabaseManagement.ReadDatabase(value.FileName);
}
}
Inside the DatabaseInfo class, there is a standard String property called Name.
However, when I run the program I get the following exception. Can anyone tell me why this happens and how to solve the issue please?
Exception has been thrown by the target of an invocation.
EDIT: I do set the value of the property which the setter above is for, in the constructor of the view model. I do this simply by setting CurrentDatabaseManagedSelection equal to an object of the DatabaseInfo class.
Think I might have found the problem... Well, I've solved it!
The issue was CurrentDatabaseManaged had not been initialized and so was equal to null when I tried setting the above property. I discovered this by adding a try.. catch in the setter method, and created a new String for CurrentDatabaseManaged.Name - the stack trace pointed to that line.
Hope that helps some one else in the future.
I've got a custom UserControl I'm working with which hosts dynamically created controls and I'm running into an odd situation where I'm seemingly losing ViewState information. In my overridden SaveViewState method on the base.SaveViewState() call, I would expect it to return me back an object containing everything that was in ViewState, but it is instead returning null.
protected override object SaveViewState()
{
object[] tempState = new object[2];
tempState[0] = base.SaveViewState(); //***suspected issue here, tempState[0] == null -- why?
//? this.ViewState["CompanyID"] returns me the guid I'm expecting
//... code instantiating and populating lstDataControlInfos
tempState[1] = lstDataControlInfos;
return tempState;
}
I put a breakpoint in that method, and I can use the immediate window to query ViewState["CompanyID"] and verify that there is indeed a CompanyID stored in ViewState. Maybe I'm misunderstanding something about ViewState, but shouldn't that call be returning what is already in ViewState (including my CompanyID)? The issue becomes a problem on postback in the overridden LoadViewState method, as I no longer have any way to get CompanyID out of ViewState; it comes back null.
protected override void LoadViewState(object savedState)
{
object[] tempState = (object[])savedState;
//tempState[0] == null, as it was stored in the previous SaveViewState call
//any reference to ViewState["CompanyID"] comes back null
base.LoadViewState(tempState[0]);
}
I mentioned I've got dynamic controls I'm serializing to and deserializing from ViewState inside this control, and those all seem to be working properly. What would cause base.SaveViewState() to return null when I know for a fact and can verify (via immediate window) there is data in ViewState during the SaveViewState call?
When you save values to ViewState, the value is marked as dirty if ViewState is being tracked.
Tracking starts in TrackViewState, which is after Initialize and before Load.
Tracking ends in SaveViewState, which is after PreRender.
If ViewState isn't being tracked when a value is set in ViewState, it won't be persisted when you call SaveViewState. This is a good thing: it means you can use ViewState during the Init phase without bloating the serialized ViewState.
When you dynamically add controls to the tree, you should note that:
Values set before you add the control to the control tree will not be persisted, even if you add the control while ViewState is being tracked.
Values set after you add the control to the control tree will be persisted, if you are in a phase where ViewState is being tracked.
At what point in the page lifecycle are you setting ViewState["CompanyID"], and are you doing so before or after you add your control to the control tree?
I have a class defined like this:
class TouchScreenDisabledGrid:DataGrid,INotifyPropertyChanged
I want to change soome of my class behaviour depanding on it's properties, that are set threw the xaml when using it in a window.
For example the following:
<my:TouchScreenDisabledGrid x:Name="dataGridView" Tag="13" />
Will cause an exception if In my constructor I try to check this value:
public TouchScreenDisabledGrid(){
Console.WriteLine(this.Tag.ToString());
}
Why is that and how can I check the propery and use it?
Objects defined in XAML are constructed using the default constructor and then their properties are set. So imagine that this:
<my:TouchScreenDisabledGrid x:Name="dataGridView" Tag="13" />
Is the moral equivalent of this:
var g = new TouchScreenDisabledGrid();
g.Name = "dataGridView";
g.Tag = "13";
It should now be obvious why Tag is null inside your constructor, hence you are getting a NullReferenceException when you call ToString().
Continuing further, you cannot use the classical model of doing something inside the constructor that depends on object properties being set. You have to find another way of achieving your goal -- what way, depends on what exactly the goal is (for example you can use INotifyPropertyChanged to detect that a property has been set; or you can listen to an event that triggers later in the lifetime of the visual and fetch the values from there).
If the property is set in XAML it will not be set in the constructor. Use OnLoaded override to do this.
The situation is this:
I have an abstract class used globally that used to reference a Session variable via a public property. We now want to change its behavior to return a property on a master page.
(By simply changing the guts of this particular property, we hope to avoid doing a lot of rewrites)
This is just a snippet of the class:
public abstract class AppSession
{
public static CaseNumber CurrentCaseNo
{
/* OLD METHOD DELETED */
get
{
if (CurrentPage.Master != null)
// property on the master page
return CurrentPage.Master.CurrentCaseNo;
else
throw new Exception("This page has no master page");
}
}
}
Above, "CurrentPage" is not real/valid. I just wrote that there to show context.
Is this even possible?
Thanks!
J
Look at the HttpContext.Current object. I believe it's Handler property will return the currently executing page. It would be easier to read a value stored in the Session that pulling it out of a property since the Session is available off of HttpContext.Current.
Building on David's answer, this can be used statically throughout your application:
Page myPage = System.Web.HttpContext.Current.CurrentHandler as Page;
if( myPage != null )
return ((MyMaster)myPage.Master).CurrentCaseNo;
I think that you would need to work with something that took a "page" object in as a parameter, and from there, you could determine if the page that was passed is your master page. And do what you need from there....
But that adds quite a bit of overhead.
The real question here is what are you trying to avoid? Trying to get rid of session and move to viewstate?
In ASP>Net using C#, I declared a variable as member of the class as follows:
public class sales: System.Web.UI.Page
{
string type=null;
}
And i have an Image Button in my UI for which I've defined the event called
protected void ImageButton2_Click(object sender, ImageClickEventArgs e)
in this method, any value assigned to variable 'type'(by any other method of the class) is not retained and only value null is being retrieved though I've assigned some value to 'type' somewhere inside the class...
What could be the problem that I cant access the assigned value????
You have to persist data between postbacks.
I recommend you to read these articles:
ASP.NET Page Life Cycle Overview
Understanding ASP.NET View State
Nine Options for Managing Persistent User State in Your ASP.NET Application
ASP.NET State Management Recommendations
This is probably a result of the render pipeline. Remember, even though your event is being fired, the page and all variables are recreated with their default value. Create it as a property with at least a backing viewstate storage.
public String Type
{
get { return ViewState["Type"].ToString(); }
set { ViewState["Type"] = value; }
}
Each time you do a request to the page, the variable is re-initialized, if it is a postback or not.
Try to put your variable in a property instead of a field (as you are doing) and initialize the propertie the first time you load the page, only if is not a postback.
You should do something like:
//on the On_Load page's event
if (!IsPostback)
Type = null;
private string Type { get; set; }
If your assigning the value in your object and then doing a postback with the button, the value will be gone unless you stored that instance of the object in the session, viewstate, or something.
string sType = "something";
Session["YourSessionTagHere"] = sType;
Once the postback occurs you can then fetch the object out and access the value from your onclick event.
string sType = (string)(Session["YourSessionTagHere"]);
It just sounds like your not accessing the same object and your object is getting lost because after each postback your string would be new.
You could also make this a bit cleaner by just setting up a property that does the session stuff for you in the get and set.