How to avoid public variable duplicate in c# - c#

I have public variables:
public static List<CompanyModel1> companies1 = new List<CompanyModel1>();
public List<URL> urls = new List<URL>();
I add more values to this variable during a function call
public void DataBind_Results()
{
..companies1.AddRange(listToAdd.OrderByDescending(c => c.compnMastery1));
}
urls.Add(new URL
{
Link = listToAdd.First().compnId1.ToString(),
Title = arrProcess[ar]
});
But my code always run twice (I see that when I use debug), I think the reason is it always have page reload.
Then my variable will be duplicate its values, and when I the data display, I see it is duplicated. How to avoid it ?

I'm going to assume you're using asp.net or something. Wrap the "add" function in an
if(!Page.IsPostBack) {
//Your add code
}

Ideally, find out why your page is loading twice then fix that.
Then add code to check whether the lists are populated at the start of each data bind before they are re-populated.

You want the variable to populate OnLoad so do something like this:
Declare your variables:
public static List<CompanyModel1> companies1;
public List<URL> urls;
The populate them when the page loads. But not if you're doing a postback.
protected override void OnLoad(EventArgs e)
{
if(!IsPostBack)
{
companies1 = new List<CompanyModel1>();
urls = new List<URL>();
}
}

Your code is running twice that means, once when you call that function and again when the page is posted back.
Put your code in
if(!IsPostBack)
{
here.....
}

Related

Declare global variables in codebehind file

In the code below, how do I declare totalSquareFeet and other variables global so that when I parse data from asp.net textboxes it becomes accessible to other methods specifically performAnalysisButton button method?
Note that the code below is not complete. I have deleted most of the code to keep my question as simple as possible. To give you a background following are the purposes of 2 buttons:
okButton_Click: Take the data from textboxes (created in asp.net webform) and perform some calculations and display results in labels.
performAnalysisButton_Click: Take the data from aforementioned textboxes and perform some calculations and display results in another textbox.
In short, all the local variables that I have declared under the okButton_Click method, I would like to use them under performAnalysisButton_Click method. I was wondering if there is a way I can avoid parsing the textbox data again?
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Create objects for fiscal year end dates (e.g. 12/31/17)
FiscalYearEnds fiscalYearEnds = new FiscalYearEnds();
firstFiscalYearEndLabel.Text = String.Format("{0:MM/dd/yyyy}", fiscalYearEnds.firstFiscalYearEndDate());
secondFiscalYearEndLabel.Text = String.Format("{0:MM/dd/yyyy}", fiscalYearEnds.secondFiscalYearEndDate());
}
protected void okButton_Click(object sender, EventArgs e)
{
// Parse values
int totalSquareFeet = int.Parse(totalSqFtTextBox.Text);
int totalOccupiedSquareFeet = int.Parse(occupiedSqFtTextBox.Text);
decimal grossRentsFirstYear = decimal.Parse(grossRentsFirstYearTextBox.Text);
decimal grossRentsSecondYear = decimal.Parse(grossRentsSecondYearTextBox.Text);
int loanAmount = int.Parse(loanAmountTextBox.Text);
double interestRate = double.Parse(interestRateTextBox.Text);
int loanTerm = int.Parse(yearlyLoanTermTextBox.Text);
}
protected void performAnalysisButton_Click(object sender, EventArgs e)
{
Analysis analysis = new Analysis();
analysis.GrossRentFirstYear = decimal.Parse(grossRentsFirstYearTextBox.Text);
analysis.GrossRentSecondYear = decimal.Parse(grossRentsSecondYearTextBox.Text);
analysisAndComments.Text = String.Format("{0}", analysis.PerformAnalysis());
}
}
After roundtrip the page returns to the client and there will be no information saved on the server unles you save it somewhere. Meaning you can hold the extra information on the page inside a hiddenfield or you can store it inside a Session or ViewState
Session This will be saved on the server(Also available if you go to other page)
Session["totalSquareFeet"] = totalSquareFeet;
Then you can read it back in performAnalysisButton_Click
int totalSquareFeet = (int)Session["totalSquareFeet"];
if you wanna clean the Session var after leaving page you can do
Session["totalSquareFeet"] = null;
ViewState This will be saved on the page(Credits to Alexandru Popa)
ViewState["totalSquareFeet"] = totalSquareFeet;
Read
int totalSquareFeet = (int)ViewState["totalSquareFeet"];
Hiddenfield This will be saved on the page
store it in a <asp:HiddenField ID="HiddentotalSquareFeet" runat="server" />
HiddentotalSquareFeet.Value = totalSquareFeet.ToString();
And read it back
if(int.TryParse(HiddentotalSquareFeet.Value, out int totalSquareFeet)){
}
If I understood your question right...
To declare a variable as global, all you need to do is to declare it outside of the function and inside of the class that you are working in:
public partial class Default : System.Web.UI.Page
{
int totalSquareFeet = 0;
protected void Page_Load(object sender, EventsArg e)
{ // And the rest of the code should be the same...
}
// Same code as you had...
}
So, it's al about removing the declaration from within the function to the outside.
I solved the problem by declaring properties at the class level and that became my global variables which I can access in button methods. Now I don't need to parse textbox values again in the button methods. See example below:
public int totalSquareFeet
{
get { return int.Parse(totalSqFtTextBox.Text); }
set { int.Parse(totalSqFtTextBox.Text); }
}

Where do I put my object when using asp

I'm relatively new to C# and VS, and currently having a play with ASP.NET, but I seem to be getting very muddled on where I should place my objects that I need to use within my webforms. As a very basic example, how could I add a counter button? With the code below, when you click the button nothing changes and the textbox just shows The count is 2'. I think this is because the page is reloading each time and therefore the Counter object gets 're' instantiated. So how do I avoid that?
Default.aspx
...
<asp:Button ID="bttnCounter" runat="server" Text="Click Me" OnClick="ButtonClick"/>
...
Default.aspx.cs
public partial class _Default : Page
{
Counter counter = new Counter();
protected void Page_Load(object sender, EventArgs e)
{
bttnCounter.Click += new EventHandler(this.ButtonClick);
}
public void ButtonClick(Object sender, EventArgs e)
{
counter.CountUp();
output.Text = "The count is " + counter.CurrentCount;
}
}
Counter.cs
public class Counter
{
public int CurrentCount { get; private set; }
public Counter()
{
CurrentCount = 0;
}
public void CountUp()
{
CurrentCount++;
}
}
I may have just completely mis understood this, but when I was using WinForms, I would include the object within the form code.
You should save it in the pages ViewState, since that is the only persistent user-based storage that isn't session bound (you can open the same page multiple times).
this.ViewState["someVar"] = yourObject;
Retrieve it later:
YourClass yourObject = (YourClass)this.ViewState["someVar"];
You are correct, the page is loading each time and thus resets your counter to zero each time you click the button.
there are a number of approaches to solve this, the simplest is perhaps to use the Session["counter"] object to store the counter and reload it on page load.
However, as you are new I would suggest you abandon this style of asp.net and instead learn the new MVC version
this has a different approach which avoids many of the page lifecycle problems of asp.net (webforms) although you will still need to store the counter either on the server, or in the page response to the user so it can be sent back in the query string, cookie or whatever

Reload Data every time I navigate to Page

I have this Windows Phone Page where I load data through the standard ViewModel scope.
public Profile()
{
InitializeComponent();
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.PersonalizedViewModel.IsDataLoaded)
{
App.PersonalizedViewModel.LoadData();
}
}
This works fine. However when I navigate to this page from some other page the data is still the same. I mean the LoadData() method should recheck updated data right? Please suggest.
EDIT:
My PersonalizedViewModelClass:
public class PersonalizationViewModel: INotifyPropertyChanged
{
public PersonalizationViewModel()
{
this.favorites = new ObservableCollection<ItemViewModel>();
this.Bar = new ObservableCollection<Bars>();
}
public ObservableCollection<ItemViewModel> favorites { get; private set; }
public ObservableCollection<Bars> Bar { get; private set; }
private string _sampleProperty = "Sample Runtime Property Value";
public string SampleProperty
{
get
{
return _sampleProperty;
}
set
{
if (value != _sampleProperty)
{
_sampleProperty = value;
NotifyPropertyChanged("SampleProperty");
}
}
}
public bool IsDataLoaded
{
get;
private set;
}
/// <summary>
/// Creates and adds a few ItemViewModel objects into the Items collection.
/// </summary>
public async void LoadData()
{
favorites.Clear();
try
{
var query = ParseObject.GetQuery("Favorite")
.WhereEqualTo("user", ParseUser.CurrentUser.Username);
IEnumerable<ParseObject> results = await query.FindAsync();
this.favorites.Clear();
foreach (ParseObject result in results)
{
string venue = result.Get<string>("venue");
string address = result.Get<string>("address");
string likes = result.Get<string>("likes");
string price = result.Get<string>("price");
string contact = result.Get<string>("contact");
this.favorites.Add(new ItemViewModel { LineOne=venue, LineTwo=address, LineThree=likes, Rating="", Hours="", Contact=contact, Price=price, Latitude="", Longitude="" });
}
if (favorites.Count == 0)
{
// emailPanorama.DefaultItem = emailPanorama.Items[1];
MessageBox.Show("You do not have any saved cafes. Long press a cafe in main menu to save it.");
}
}
catch (Exception exc)
{
MessageBox.Show("Data could not be fetched!", "Error", MessageBoxButton.OK);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Implementation of PersonalizedViewModel:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await App.PersonalizedViewModel.LoadData();
user_tb.Text = ParseUser.CurrentUser.Username;
if (NavigationContext.QueryString.ContainsKey("item"))
{
var index = NavigationContext.QueryString["item"];
var indexParsed = int.Parse(index);
mypivot.SelectedIndex = indexParsed;
}
if (NavigationService.BackStack.Any())
{
var length = NavigationService.BackStack.Count() - 1;
var i = 0;
while (i < length)
{
NavigationService.RemoveBackEntry();
i++;
}
}
}
I don't see the problem, however, I think you need to narrow in on the problem.
First off, you are calling LoadData from 2 places. 1 from MainPage_Load and 1 from OnNavigatedTo. In MainPage_Load it is conditional and in OnNavigatedTo it is always being called. I suggest that you get to a single path through the code instead of 2 so that you don't get different experiences. I personally recommend (without knowing all the details) that you call load data from OnNavigatedTo instead of MainPage_Load. If you want to do it conditionally that is fine but if you are loading the data from memory, it really is unnecessary as you won't improve performance anymore than a few milliseconds. Also, if you are not loading from memory, you may not want to load it conditionally because the underlying data may have changed. In either case, the choice to load data or not should be moved out of the view and into the data layer (but that is for another post).
Once you have a single path chosen (i.e. calling LoadData from MainPage_Load or OnNavigatedTo) you should use your debugger. Put a break point in LoadData method and if it is being called appropriately, then your problem is more specific than your posted question. Here are some questions to think about (you may want to start from the last question and work your way backward)
Questions:
Is LoadData being called appropriately?
Does ParseObject have the correct data?
Is the ParseUser...UserName set properly?
Is the foreach being executed the proper # of times (i.e. does the result of your query have the right # of items?)
Couple Code Tips completely unrelated to this problem:
Single Path through code. Don't call LoadData from more than one place.
Don't call favorites.clear() twice in the same method. (it is called twice in LoadData)
Consistent naming. favorites is lowercase but Bar is upper case.
User proper data types. On your ItemViewModel you have Hours, Latitude, and Longitude. You have them as strings. These clearly are not strings. Also, you should not set them to empty. Empty means they have been set to a value. Emtpy is a valid value. Null means not set. To keep your objects clean and accurate you want to be accurate in how you set things and then deal appropriately with the impact. If you really really want them to be initialized to empty strings, then at least do it in the constructor of ItemViewModel so that every caller doesn't have to know how to initialize every property. I guarantee this is leading to buggy code if you continue using this practice.
Please take the comments as constructive criticism not criticism. I know many people don't like to hear these things but the teams I lead write bugs until they start following these types of guidelines.
Good luck,
Tom
Instead of defining this
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
into constructor i.e. Profile I would suggest remove this code from Constructor and add it into your OnNavigatedTo. so the data will load after navigation
Your OnNavigatedTo Method looks like follows
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
Might be your problem will solve.
Edit
Try this query
var results = (from find in ParseObject.GetQuery("Favorite").WhereEqualTo("user", ParseUser.CurrentUser.Username) select find);
Tried this:
var query = from favorite in ParseObject.GetQuery("Favorite")
where favorite.Get<string>("user") == ParseUser.CurrentUser.Username
select favorite;
IEnumerable<ParseObject> results = await query.FindAsync();
I had a similar Problem.All u want to do here is generate a new instance of the Page.U can do this in two Ways.
One Way is by forcing a GUID along with Page Navigation URI that will create a New Instance of the Page and your Load Data() will work.
NavigationService.Navigate(new Uri(String.Format("/MainPage.xaml?item={0}", Guid.NewGuid().ToString()), UriKind.RelativeOrAbsolute));
The Second Way to implement that Part of your Page in a User Control .Like create a User Control for Load Data() and put it in constructor.It will generate a new Instance everytime you load the Page.
If the problem persists in the front end,you can try this.
1.have you mentioned the below attribute in your xaml page?
<UserControl Loaded="MainPage_Loaded">
So that every time the page loads the data will get loaded on to the page.
2.The data must exist, if you have no problem in the code behind as it is a WPF application and not a web page.
Hope you find it useful.
Two changes required..
Remove the this.Loaded from OnNavigatedTo. That may not be required.
Second move the LoadData to OnNavigatedTo method
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
// this.Loaded += new RoutedEventHandler(MainPage_Loaded);
if (!App.PersonalizedViewModel.IsDataLoaded)
{
App.PersonalizedViewModel.LoadData();
}
}
For the purpose of debugging, you can remove the line if (!App.PersonalizedViewModel.IsDataLoaded) and try.

Get data from user control since Webpage

I have a simple question in asp.net.
I want to know if it is possible to get data from controls in my user control directly . I want to do it without using Session variable,Viewstate ...
EDIT: I now use the method of declaring public variables in the UC.
Here is a part of Page_load from my parent page:
this.plan_action = (UCPlan)Page.LoadControl("~/Association/UCPlan.ascx");
PlaceHolder1.Controls.Add(this.plan_action);
if (this.plan_action.Validate == true)
{
CheckBox1.Checked = true;
//String référence = Session["liste_action"].ToString();
for (int i = 0; i < this.plan_action.List1.Count; i++)
{
Label8.Text += this.plan_action.List1[i].Référence + "/";
//Label8.Text += "/";
}
}
but my variable validate stay to false.
Here is the code where I change the value of the validate variable with it declaration:
private bool validate;
public bool Validate
{
get { return validate; }
set { validate = value; }
}
protected void Button2_Click(object sender, EventArgs e)
{
//myCommand.Connection = myConnection;
//Session["liste_action"] = this.List;
this.Validate = true;
//Response.Redirect("../Risques_folder/AjouterRisque.aspx");
}
Thank you for your help,
Quentin
UPDATE due to new information
You need to learn about the sequence of events in ASP.NET.
The Load of the page happens a long time before the Click handler of Button2 in your UserControl... so the Validate property is always going to be set to false.
You have two obvious options (as I see it)...
Keep the creation of the UserControl in your Page_Load (or preferably, move it to your Page_Init, as this is normally the most appropriate place for it). Then place your check for the Validate property in a Page_PreRender.
Or, create an Event in your UserControl, Raise that event on the click of Button2, and handle the event in the Page.
ANOTHER UPDATE
For the 2nd of the two options above, in your UserControl class have the following...
public delegate void ButtonClickedDelegate(object sender, EventArgs e);
public event ButtonClickedDelegate ButtonClicked;
In the Button2_Click method of the UserControl (after setting the this.Validate = true;) call...
ButtonClickedDelegate(sender, e);
In the Page_Init of the Page, put something like...
ctrl1.ButtonClicked += new UCPlan.ButtonClickedDelegate(ctrl1_ButtonClicked);
And then have a new method called something like
void ctrl1_ButtonClicked(object sender, EventArgs e)
{
if (ctrl1.Validate)
{
...
}
}
Remember, as you control the delegate you can pass whatever information you want, including an entire class. So instead of calling the Validate property, create a new instance of the class you want, and pass that as a delegate parameter.
You can find more information on delegates and events on MSDN.
ORIGINAL ANSWER
Unless I've missed something, this is a very simple ASP.NET concept...
You can create properties and/or methods.
For example, as a property...
public string MyProperty
{
get { return "My Property Value"; }
}
Or as a method
public string MyMethod()
{
return "My Method Value";
}
If you're talking about passing the values between the UserControl and the ASP.NET Page that contains it, then in your Page, you can simply call the property or method. If your control was called (for example) myCtrl, then you can something like...
string prop = myCtrl.MyProperty;
string meth = myCtrl.MyMethod();
(On the back of the great comment from AHMED EL-HAROUNY)
If you're talking about passing the values to the client side page, then you can use the same properties / methods directly in the HTML markup. However, in this case, the properties / method can be declared as protected rather than public
For instance, to display the value...
<%=MyProperty%>
Or
<%=MyMethod()%>
Or if you're going to use the value in javascript, something like...
var myProp = "<%=MyProperty%>";
Yes That is possible, But exposing the controls in the UserControl as Public.

Why is the boolean variable always resetting to false;

I have a boolean variable declared at the top of a class and when a radio button is selected on a page, the variable gets set to true, but when the page is reloaded, the variable gets reset back to false. One way I have handled this was by using the static keyword, but I am not sure if this is the best way to handle this. Here is the class where I tried doing things in the Page_Load event, but it is still resets the variables to false.
public class SendEmail
{
bool AllSelected;
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
AllSelected = false;
}
}
protected void rbAll_SelectedIndexChanged(object sender, EventArgs e)
{
if(rbAll.SelectedValue == "All")
AllSelected = true;
}
public Send()
{
if(AllSelected)
{
//Send Email. Never runs because AllSelected is always false;
}
}
}
When the page gets reloaded, a new instance of your page class is created so any values from the last server interaction are lost. Put the value into viewstate if you want it to persist across postbacks:
bool AllSelected
{
get
{
object o = ViewState["AllSelected"];
if(o == null) return false;
return (bool)o;
}
set
{
ViewState["AllSelected"] = value;
}
}
The ViewState collection is written in a hidden element into the form in the client's browser, and posted back and restored the next time they click a button or do any other "postback" type action.
Every time asp.net serves a page, it creates a new instance of the page class. This means that AllSelected will always be auto initialized to false.
My suggestion, unless there is something I don't see here, is to just call Send() from your SelectedIndexChanged method.
You need your variable to be stored. I'd suggest storing it in ViewState or if you want to stay away from ViewState, hide it in a form element on the page.
Also, I'm not seeing where Send is being called.
Your boolean is an instance variable, so it will get the default value (which is false for bools) every time you create a new instance of your class.
Remember, every request to your page uses a brand new instance of your page class. This includes postbacks.
Not to jump down on you or anything...but why not just check if
rbAll.SelectedValue == "All"
in your send function?
No storage...no populating the ViewState or Session with data that isn't needed...
I don't really know if this is going to be handy in asp.net but I create a new bool in property.settings so that it remembers the bool whenever I close or restart the application. But I think this is more for winforms.

Categories