In a parentclass I call a function defined in the child class and parse the values I need through.
ParentClass.ascx
protected void Page_Load
{
if(info != null)
ControlIWantToGetInformationTo.SetInfo(info);
}
ChildClass.ascx
public void SetInfo(Info info)
{
someTextBox.Text = info.TheVariableWithin.ToString();
}
What I can gather is that that ParentClass(control) loads and does the method, but when the ChildClass(control) page loads it resets the previously set variable to null how can I work around this?
Use Session. In your method, instead of setting the values of your controls, use an object and fill the properties of your object and save it to Session when you are done. In your childclass, load your values from the object which you saved into Session.
//Parentclass
protected void Page_Load
{
if(info != null)
{
MyControlObject myObj = new MyControlObject();
myObj.prop1 = txt1.Text;
myObj.prop2 = txt2.Text;
Session["myObj"] = myObj;
}
}
//Childclass
public void SetInfo(Info info)
{
MyControlObject myObj = Session["myObj"] as MyControlObject;
if(myObj != null)
{
//assign the values to your controls
Session["myObj"] = null; //when you are done, clear the session.
}
}
I think you are facing problem for case sensitivity.
try this
someTextBox.Text = info.TheVariableWithin.ToString();
Related
Okay so I'm adapting a C# program to an asp program and I have a main form which contains a list box and another which adds new information to the list box. I can fill in the 2nd form and hold values in Application["getData"]; but when I go to the other page I need to run the following code.
public void AddGig()
{
AddGigForm frm = new AddGigForm();
if (Application["getData"] != null)
{
Application["saveData"] = Application["getData"];
gigList.addGig(frm.GetData());
UpdateListbox();
}
I run into problems at gigList.addGig as it goes back to the method GetData() on the 2nd form. I just have no idea what else to use.
GetData method:
public GigOpportunity GetData()
{
Application["GetData"] = new GigOpportunity
(txtId.Text, gigDate.SelectedDate, txtVenue.Text, txtGenre.Text,
Convert.ToDouble(txtCost.Text), Convert.ToInt32(txtCapacity.Text), chkHeadliner.Checked, txtMainAct.Text, chkEngineer.Checked);
return new GigOpportunity(txtId.Text, gigDate.SelectedDate, txtVenue.Text, txtGenre.Text, Convert.ToDouble(txtCost.Text), Convert.ToInt32(txtCapacity.Text), chkHeadliner.Checked, txtMainAct.Text, chkEngineer.Checked);
}
addGig method:
public void addGig(GigOpportunity gigOpportunity)
{
//Make sure a gig with this id does not already exist
foreach (GigOpportunity g in gigList)
{
if (g.GigId == gigOpportunity.GigId)
{
throw new DuplicateIdException();
}
}
gigList.Add(gigOpportunity);
}
I understand now your problem. You musn't think like in windows form. You declared those method inside other form. When you call it by assigning a new Form object you will not get the value inside as they have been disposed after you change the page.
So in your case:
if (Application["getData"] != null)
{
Application["saveData"] = Application["getData"];
gigList.addGig((GigOpportunity)Application["getData"]);
UpdateListbox();
}
But I will suggest you to use Session object instead of Application object.
You can read more about it here
So you have to do like this:
if (Session["getData"] != null)
{
Session["saveData"] = Session["getData"];
gigList.addGig((GigOpportunity)Session["getData"]);
UpdateListbox();
}
You don't need to create the second form object AddGigForm and you must be sure to call your methodGetData in the form where is it declared to assign your Session.
I am working on a web app;ication based on asp.net with c#,I have two methods specified below.
public partial class ClerkReception_CreateRecords : System.Web.UI.Page
{
string patid;
protected void ddryear_textchanged(object sender, EventArgs e)
{
string month = "";
if (ddrmonth.SelectedItem.Text == "Jan")
{
month = "01";
}
else if (ddrmonth.SelectedItem.Text == "Feb")
{
month = "02";
}
else if (ddrmonth.SelectedItem.Text == "Mar")
{
month = "03";
}
string year;
year = ddryear.SelectedItem.Text;
string locid = Session["Location"].ToString();
patid = locid + month + year;//Ex:AT112013
myConnection obj = new myConnection();
//string result = obj.fnDisplayManualRecords(year, month, locid);
string result = obj.fnDisplayManualRecords1(patid);
txtlast.Text = result.ToString();
if (ddrmonth.SelectedItem.Text != null || ddryear.SelectedItem.Text != null)
{
txtlast.Visible = true;
lbllast.Visible = true;
BtnProceed.Visible = true;
}
}
This is a method used when a item is selected from dropdownlist,where the patid returns the value.
I need to access the same value of patid inside a another method shown below,Hence I declared the patid as global variable so that I can access the value in any method.But its giving null.How to retieve the vale from one method to another method?
protected void BtnProceed_Click(object sender, EventArgs e)
{
string x = patid;//shows null
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("select top 1(SUBSTRING(patientid,9,4)) as MaxpatientID from Patient_Data where PatientID like '"+patid+"%' order by PatientID desc;", cn))
{
try
{
cn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
//int Patcount;
if (rdr.Read())
{
int Patcount = int.Parse(rdr["MaxpatientID"].ToString());
// if(Patcount == 0)
}
}
}
catch (Exception ex)
{
// handle errors here
}
}
}
}
}
The global variables are created / intialized between postback in asp.net and they do not retain the values between postback as http is stateless protocol, you need to use ViewState for that. You can read more about ViewState and Stateless protocol over here.
To set value in ViewState
ViewState["patid"] = locid + month + year;//Ex:AT112013;
To get value from ViewState
string patid = ViewState["patid"].ToString();
View State
View state's purpose in life is simple: it's there to persist state
across postbacks. (For an ASP.NET Web page, its state is the property
values of the controls that make up its control hierarchy.) This begs
the question, "What sort of state needs to be persisted?" To answer
that question, let's start by looking at what state doesn't need to be
persisted across postbacks. Recall that in the instantiation stage of
the page life cycle, the control hierarchy is created and those
properties that are specified in the declarative syntax are assigned.
Since these declarative properties are automatically reassigned on
each postback when the control hierarchy is constructed, there's no
need to store these property values in the view state. You can read
more about viewstate here.
Welcome to the world of post backs, each post back recreates the page (class) variables, so you need to save it before post back or it will be gone.
Use a cache object, such as Session to maintain values between post back and page navigation. Session gives you the power to store and retrieve objects across multiple pages in your application, including just one if you are continually posting back to it.
You can use Session, like this:
Storing value in Session:
Session["ValueToKeep"] = "My important information";
Retrieving value from Session:
// Make sure it is in session cache before we try to get it
if(Session["ValueToKeep"] != null)
{
string valueINeed = Session["ValueToKeep"].ToString();
}
Note: All items stored in Session are Objects thus the usage of .ToString() on the Session item. An item is boxed as an object when inserted into Session, but must be unboxed (cast) when retrieved.
You class level variables are re-created on postback. You will need to persist them somewhere that continues across requests.. such as ViewState, Session, etc.
The best way to interact with two methods / functions / event-function in side class is just declaring its accessible modifiers to public and you can call any object of that class after initialize some value to it.
public void ddryear_textchanged(object sender, EventArgs e) {....}
public void BtnProceed_Click(object sender, EventArgs e) {....}
create one variable inside class like string x; and initialize it in constrictor { x="some text "; } this is how code works...
There are many ways to get the value of global parameter,
one way is to define the parameter as static
I am using a PropertyGrid to display the content of an object to the user.
This PropertyGrid is synchronized with an Excel sheet, assuming a cell value match a property value.
As the user selects a property in the PropertyGrid, the application highlights the corresponding cell in the Excel sheet which is opened beside. I can do this using the SelectedGridItemChanged event.
Now, I want to have a property selected in my PropertyGrid when the user selects a cell in the Excel sheet.
void myWorkbook_SheetSelectionChangeEvent(NetOffice.COMObject Sh, Excel.Range Target)
{
if (eventMask > 0)
return;
try
{
eventMask++;
this.Invoke(new Action(() =>
{
propertyGrid1.SelectedGridItem = ... // ?
}
}
finally
{
eventMask--;
}
}
I noticed that the SelectedGridItem can be written to.
Unfortunately I do not find a way to access the GridItems collection of my PropertyGrid so I can look for the right GridItem and select it.
How can I do this?
You can get all the GridItems from the root. I am using the below code to retrieve all the griditems within a property grid
private GridItem Root
{
get
{
GridItem aRoot = myPropertyGrid.SelectedGridItem;
do
{
aRoot = aRoot.Parent ?? aRoot;
} while (aRoot.Parent != null);
return aRoot;
}
}
and pass the root to the below method
private IList<GridItem> GetAllChildGridItems(GridItem theParent)
{
List<GridItem> aGridItems = new List<GridItem>();
foreach (GridItem aItem in theParent.GridItems)
{
aGridItems.Add(aItem);
if (aItem.GridItems.Count > 0)
{
aGridItems.AddRange(GetAllChildGridItems(aItem));
}
}
return aGridItems;
}
I came up against this quite a bit a project so I wrote an extension method for it:
if (!SetupManagerSettings.BootStrapperLocation.IsFile()) // Just another extension method to check if its a file
{
settingsToolStripMenuItem.Checked = true; // Event handler OnChecked ensures the settings panel is unhidden
settingsPropertyGrid.ActivateControl();
settingsPropertyGrid.SelectPropertyGridItemByName("BootStrapperLocation"); // Here is the extension method
return false;
}
Here is the extension method with a private, supporting method for traversing the hierarchy of objects (if this applies to your object model):
public static bool SelectPropertyGridItemByName(this PropertyGrid propertyGrid, string propertyName)
{
MethodInfo getPropEntriesMethod = propertyGrid.GetType().GetMethod("GetPropEntries", BindingFlags.NonPublic | BindingFlags.Instance);
Debug.Assert(getPropEntriesMethod != null, #"GetPropEntries by reflection is still valid in .NET 4.6.1 ");
GridItemCollection gridItemCollection = (GridItemCollection)getPropEntriesMethod.Invoke(propertyGrid, null);
GridItem gridItem = TraverseGridItems(gridItemCollection, propertyName);
if (gridItem == null)
{
return false;
}
propertyGrid.SelectedGridItem = gridItem;
return true;
}
private static GridItem TraverseGridItems(IEnumerable parentGridItemCollection, string propertyName)
{
foreach (GridItem gridItem in parentGridItemCollection)
{
if (gridItem.Label != null && gridItem.Label.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
{
return gridItem;
}
if (gridItem.GridItems == null)
{
continue;
}
GridItem childGridItem = TraverseGridItems(gridItem.GridItems, propertyName);
if (childGridItem != null)
{
return childGridItem;
}
}
return null;
}
I looked at the above options and did not like them that much, I altered it a bit found that this works well for me
bool TryFindGridItem(PropertyGrid grid, string propertyName, out GridItem discover)
{
if (grid is null)
{
throw new ArgumentNullException(nameof(grid));
}
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("You need to provide a property name", nameof(propertyName));
}
discover = null;
var root = pgTrainResult.SelectedGridItem;
while (root.Parent != null)
root = root.Parent;
foreach (GridItem item in root.GridItems)
{
//let's not find the category labels
if (item.GridItemType!=GridItemType.Category)
{
if (match(item, propertyName))
{
discover= item;
return true;
}
}
//loop over sub items in case the property is a group
foreach (GridItem child in item.GridItems)
{
if (match(child, propertyName))
{
discover= child;
return true;
}
}
//match based on the property name or the DisplayName if set by the user
static bool match(GridItem item, string name)
=> item.PropertyDescriptor.Name.Equals(name, StringComparison.Ordinal) || item.Label.Equals(name, StringComparison.Ordinal);
}
return false;
}
it uses a local method named match, if you're version of C# does not allow it then just put it external to the method and perhaps give it a better name.
Match looks at the DisplayName as well as the property name and returns true if either is a match, this might not be what you would like so then update that.
In my usecase I need to select the property based on a value the user can select so call the above method like this:
if (TryFindGridItem(pgMain, propertyName, out GridItem gridItem))
{
gridItem.Select();
}
It could theoretically never not find it unless the user selects a string that is not proper this way the if can be updated using an else .. I rather keep it safe then have a null-pointer exception if I can't find the name specified.
Also I am not going into sub classes and lists of classes as my use case doesn't need that, if yours does than perhaps make recursive calls in the GridItem.
Small note, replace GridItem with var and the code brakes as at compile time the IDE has no clue what a GridItemCollection returns…
Working on a page where I create new instances of a usercontrol I wrote, based on data. I pass in filtered data to the user control using constructor injection. However, when the user controls render, only the last set of data injected in is rendered for all user controls. It appears I'm referencing the same instance rather than creating a new, independent one. Ideas?
protected void Page_Init(object sender, EventArgs e)
{
var data = <my data comes from here>;
var yearsInData = data.OrderByDescending(x=>x.Year).Select(x => x.Year).Distinct();
foreach(var year in yearsInData)
{
var employers = data.OrderBy(x=>x.EmployerName).Where(x => x.Year == year).Select(x => x.EmployerName).Distinct();
foreach (var employer in employers)
{
var eob = data.Where(x => x.Year == year).Where(x => x.EmployerName == employer);
if (eob.Count() > 0)
{
var ctl = LoadControl(#"~\Shared\Controls\AnnualEOBControl.ascx", eob);
pnlMain.Controls.Add(ctl);
}
}
}
}
Here is the LoadControl method:
private UserControl LoadControl(string userControlPath, params object[] constructorParameters)
{
var constParamTypes = new List<Type>();
foreach (var constParam in constructorParameters)
{
constParamTypes.Add(constParam.GetType());
}
var ctl = Page.LoadControl(userControlPath) as UserControl;
// Find the relevant constructor
if (ctl != null)
{
var constructor = ctl.GetType().BaseType.GetConstructor(constParamTypes.ToArray());
// And then call the relevant constructor
if (constructor == null)
{
throw new MemberAccessException("The requested constructor was not found on : " + ctl.GetType().BaseType);
}
constructor.Invoke(ctl, constructorParameters);
}
// Finally return the fully initialized UC
return ctl;
}
It smells like a closure issue. My hunch is eob is merely being reassigned a value during each iteration as opposed to recreated. Since your controls all reference eob as opposed to the data returned by eob, they would all use the same value when it's time to render.
What does your LoadControl overload look like? I read through the article you referenced, but I'd like to see what you did, specifically. I wonder if simply reassigning values from eob to a variable declared inside your LoadControl method would get you over the hump. Force the controls to use a variable from a tighter scope so they can't physically see each other's arguments.
Edit: Found an SO reference on the topic: What are 'closures' in .NET?
Give this a whirl:
private UserControl LoadControl(string userControlPath, params object[] constructorParameters)
{
var constParamTypes = new List<Type>();
foreach (var constParam in constructorParameters)
{
constParamTypes.Add(constParam.GetType());
}
var ctl = Page.LoadControl(userControlPath) as UserControl;
// Find the relevant constructor
if (ctl != null)
{
var constructor = ctl.GetType().BaseType.GetConstructor(constParamTypes.ToArray());
// And then call the relevant constructor
if (constructor == null)
{
throw new MemberAccessException("The requested constructor was not found on : " + ctl.GetType().BaseType);
}
// constructor.Invoke(ctl, constructorParameters);
object[] cp = constructorParameters;
constructor.Invoke(ctl, cp);
}
// Finally return the fully initialized UC
return ctl;
}
If I had this issue and there was a base class I could instrument and a way to produce a trace of some kind without too much trouble, I'd
put a const instance member Guid and a DateTime, both initializes it in the constructor
put a few ms sleep between separate calls to the constructor so the timestamps
I'm just thinking that might give a hint as to what's going on and lead to the root of it.
I have an control that inherits from another control (TxTextControl). I have a SelectedText property that basicaly wraps the base SelectedText property, which is apparently needed because my control is implementing an interface with that property. The code is this:
public string SelectedText
{
get
{
return base.Selection.Text; // Error here (#1042)
}
set
{
if (base.Selection == null)
{
base.Selection = new TXTextControl.Selection(0, 0);
}
base.Selection.Text = value;
}
}
When I drop this control on a form, no problems. It compiles and runs. Everything looks great. However, when I save, close then reopen the form, the form designer shows this error:
Object reference not set to an instance of an object.
1. Hide Call Stack
at Test.FormattedTextBox2.get_SelectedText() in C:\Projects\Test\FormattedTextBox2.cs:line 1042
Anyone know what is going on? I'm about to pull out my last hair...
UPDATE:
darkassisin93's answer wasn't exactly correct, but that was because my posted code wasn't exactly accurate. I needed to test if base.Selection was null before attempting to access a property of that object. In any case, that answer got me headed in the right direction. Here is the actual solution:
public string SelectedText
{
get
{
string selected = string.Empty;
if (base.Selection != null)
{
selected = base.Selection.Text;
}
return selected;
}
set
{
if (base.Selection == null)
{
base.Selection = new TXTextControl.Selection(0, 0);
// Have to check here again..this apparently still
// results in a null in some cases.
if (base.Selection == null) return;
}
base.Selection.Text = value;
}
}
Try replacing
return base.SelectedText;
with
return base.SelectedText ?? string.Empty;
It's most likely because the base class's SelectedText property is set to null.