I'd like to bind a List<StockInList> to a GridView, show them to user, and get them back(perhaps user will edit them) to do something else. However, when I retrieved the bound item stockInLists, it's null. Reason I guess is that ASP create a new Code-Behind class Add_Inventories to handle request, so I lost the access to my bound item stockInLists.
Am I doing something wrong? What should I do to get them back correctly?
public partial class Add_Inventories : System.Web.UI.Page
{
private ShoppingDbContext shoppingDbContext = new ShoppingDbContext();
private List<StockInList> stockInLists;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var stockInListsFromSession =(List<StockInList>)Session["stock_in_list"];
if (stockInListsFromSession != null)
{
//save the stockInLists in private filed, so that I can get them back, however it's null when method `Add()` invoke.
stockInLists=new List<StockInList>(stockInListsFromSession);
GridView1.DataSource = stockInLists;
GridView1.DataBind();
}
else
{
//...
}
}
}
protected async void Add(object sender, EventArgs e)
{
foreach (var stockInList in stockInLists)
{
shoppingDbContext.StockInLists.Add(stockInList);
}
await shoppingDbContext.SaveChangesAsync();
Response.Redirect(Request.Url.AbsoluteUri);
}
}
The data in variables are lost when page is refreshed(Scope), to prevent it we should use Sessions, viewstate etc or make that variable as static(Not recommended).
In your case value stored in stockInLists will be lost if the page is refreshed,
store its data in viewstate ViewState["stockInLists"] = stockInLists;
store its data in Session Session("stockInLists") = stockInLists; (Recommended)
make it a static variable private List<StockInList> stockInLists; (Not Recommended)
I hope you understand it :)
Related
I'm trying to make an application where the administrator can change some global values that it will affect the application for every user.
I tried to use static
Class
public static class Inventario
{
public static int FiltroEtiquetas;
public static int NumLocalizacoes;
public static void GetInventario()
{
}
}
Page
protected void Page_Load(object sender, EventArgs e)
{
txtFiltroEtiquetas.Text = Inventario.FiltroEtiquetas.ToString();
txtNumLocalizacoes.Text = Inventario.NumLocalizacoes.ToString();
}
protected void btnSaveInventaryChanges_Click(object sender, EventArgs e)
{
Inventario.FiltroEtiquetas = Convert.ToInt32(txtFiltroEtiquetas.Text);
Inventario.NumLocalizacoes = Convert.ToInt32(txtNumLocalizacoes.Text);
Page.ClientScript.RegisterStartupScript(this.GetType(), "CallMyFunction", "ShowToast('OK', 'topCenter','success', 'Alterações Guardadas com sucesso.', '2000')", true);
}
Whenever i open the modal the value is always 0, it won't save the changes
On page load you are resetting the both the textboxes with your global variables and on button click you are doing reverse so its kind of reset. That's why you are seeing 0 value.
You need to remove the code from page_load or you need to apply some condition over that.
You can implement something like this:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
txtFiltroEtiquetas.Text = Inventario.FiltroEtiquetas.ToString();
txtNumLocalizacoes.Text = Inventario.NumLocalizacoes.ToString();
}
}
I think its really not a good idea to use the static variable in this scenario. I think you are better off using a application variable.
I am trying to pass a simple string between pages but I don't know how to.
I created a test app where I click a button, the the value of "a" will pass on the next page (Page1.xaml.cs)
private void button1_Click(object sender, RoutedEventArgs e)
{
string a = "hello";
Page2 p2 = new Page2();
NavigationService.Navigate(p2, a);
}
Now, I want to extract the data from Page1 (Page2.xaml.cs)
private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
{
string str = (string)e.ExtraData;
}
And then subscribing in the constructor (Page2.xaml.cs)
public Page2()
{
InitializeComponent();
NavigationService.LoadCompleted += NavigationService_LoadCompleted;
}
However when I ran the program I get an error. Can someone point out what am I missing?
Without a good Minimal, Complete, and Verifiable code example, it's impossible to know for sure everything that would be needed to address your question. However, if all you're asking is how to allow data to pass from one page to the next when navigating, it seems to me that the NavigationService.Navigate(object, object) overload would be useful for you.
The second parameter is the data you want to pass. The target page can handle the NavigationService.LoadCompleted event (or any other appropriate one you prefer), where the object value that was passed to the Navigate() method can be retrieved via the NavigationEventArgs.ExtraData property.
For example, in your first page:
private void button_Click(object sender, RoutedEventArgs e)
{
Page2 p2 = new Page2();
NavigationService.Navigate(p2, v.str);
}
then in your second page:
private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
{
string str = (string)e.ExtraData;
// do whatever with str, like assign to a view model field, etc.
}
Of course, you'll subscribe the event handler, e.g. in your page's constructor or in XAML. For example:
public partial class Page2 : Page
{
public Page2()
{
InitializeComponent();
NavigationService.LoadCompleted += NavigationService_LoadCompleted;
}
private void button_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
{
string str = (string)e.ExtraData;
// do whatever with str, like assign to a view model field, etc.
}
}
Instead of setting the textbox DataContext, set the entire page’s datacontext to some class ie the ViewModel for page1. Implement the interface INotifyPropertyChanged and ensure that in the set of the string property, the NotifyPropertyChanged(“ElementName”) is raised.
Now create a new view with a corresponding view model like this which should also implement the interface INotifyPropertyChanged. Create a textbox and bind it to a string property like in first page. Ensure TwoWay binding for both properties to ensure both target and source is updated while data is changed.
Create the instance of both viewModels in MainWindow. When user navigates to 2nd user control, set
Page2ViewModel.TextBoxString = Page1ViewModel.TextBoxString;
Like this do vice versa while navigating from Page2 to Page1.
Page1ViewModel.TextBoxString = Page2ViewModel.TextBoxString;
This way, both the textboxes will be updated during navigation.
This is just an overall idea. You need to learn more about MVVM and WPF from some tutorials. Search in google.
Here is my example, maybe it helps someone
in Page1.cs
examsStr = result.Content.ReadAsStringAsync().Result;
List<Exam> exams = JsonConvert.DeserializeObject<List<Exam>>(examsStr);
for (int i = 0; i < exams.Count; i++)
{
btnExam.Click += BtnExam_OptionsShow;
btnExam.DataContext = exams[i];
}
private void BtnExam_OptionsShow(object sender, EventArgs e)
{
ExamRead examPage = new ExamRead();
examPage.DataContext = ((sender as Button).DataContext as Exam);
this.NavigationService.Navigate(examPage);
}
in Page2.cs
this.Loaded += ExamRead_Loaded;
private void ExamRead_Loaded(object sender, RoutedEventArgs e)
{
examObj = (exam.DataContext as Exam);
(exam.Children[2] as Label).Content = examObj.ExamName + " - Exam Options";
}
Page2 has attribute Name="exam" and examObj is global variable in that Page2 class
I have 2 Asp button in a page (buttonUsername and buttonReset). First one perform an AD search, and set a private variable, while second button perform an action, using variable previously set.
public partial class ResetPassword : System.Web.UI.Page {
private UserPrincipal tmpPwdUser;
protected void buttonUsername_Click(object sender, EventArgs e) {
this.tmpPwdUser = ...
}
protected void buttonReset_Click(object sender, EventArgs e) {
myObj.myFunction(this.tmpPwdUser); // --> this.tmpPwdUser is void
}
}
My problem: this.tmpPwdUser is correctly set in buttonUsername_Click function, but when buttonReset_Click event is triggered, variable this.tmpPwdUser is null. I guess that when event is triggered, page is reloaded, so each local variable is reset. Is there a way to preserve state when button si clicked?
As you suspect, a new instance of the form is created for the new request. You have to preserve the value of the variable between those requests. One way to do this is to store the value in ViewState.
You can create a helper property that stores and retrieves the value from ViewState:
private UserPrincipal TmpPwdUser
{
get
{
return ViewState["UniqueViewStateKey"] As UserPrincipal;
}
set
{
ViewState["UniqueViewStateKey"] = value;
}
}
try using the OnEvent property instead of the onclick
Poperty on button ( OnCommand="Submit_Command")
in code behind
Submit_Command(object sender, CommandEventArgs e)
{
}
I have a custom class creating a dropdownlist control as below:
public class IHGridView : System.Web.UI.WebControls.WebControl
{
private string _dataSource = "not set yet";
public string DataSource
{
get { return _dataSource; }
set { _dataSource = value; }
}
}
EDIT:
protected override void OnInit(EventArgs e)
{
// VIewState is alive. When I select an option and submit, after postback it's selected value is the one I selected.
this.Controls.Add(_dropDownList);
}
or
protected override void CreateChildControls()
{
// VIewState is dead. When I select an option and submit, after postback it's selected value is the default one.
this.Controls.Add(_dropDownList);
}
So, now I come up with the result that I have to add control in "OnInit" void.
But, this "OnInit" is the first void that this class writes.
If I want to use a property like "DataSource" before, "OnInit" void...
How would I do that?
EDIT:
protected void Button1_Click(object sender, EventArgs e)
{
IHGridViewTest2.DataSource = "fired";
}
DataSource is set when the button in aspx page is fired.
why would you want to add _dropDownList twice? once in the OnInit should be enough, and OnInit is where it should be added if you want it in the control collection - thus having viewstate persisted and restored.
to access and bind _dropDownList for example, override the DataBind method - at which point all the properties will be available to you.
protected override void DataBind(){
base.DataBind();
_dropDownList.DataSource = this.DataSource;
_dropDownList.DataBind();
}
this is pseudo code, and has not been tested or validated
EDIT:
Call overriden DataBind method
protected void Button1_Click(object sender, EventArgs e)
{
IHGridViewTest2.DataSource = "fired";
IHGridViewTest2.DataBind();
}
I am building a Asp.net Application. I need to save a HashTable in a session.
At page load i am writing
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Session["AttemptCount"]=new Hashtable(); //Because of this line.
}
}
Here problem is, when a user refresh the page, session["AttemptCount"] also get refreshed.
I want to know where should I declare
Session["AttemptCount"]=new Hashtable();
So that my seesion do not get refeshed.
EDIT In Global.asax, this session will get started, as soon as user opens the website. I want to creat this session only if user go to a particular page. i.e Login.aspx
Do it in the Session_Start method in your Global.asax like so...
protected void Session_Start(object sender, EventArgs e)
{
Session["AttemptCount"]=new Hashtable();
}
Update:
Then simply just do a check to see if the session variable exists, if it doesn't only then create the variable. You could stick it in a property to make things cleaner like so...
public Hashtable AttemptCount
{
get
{
if (Session["AttemptCount"] == null)
Session["AttemptCount"]=new Hashtable();
return Session["AttemptCount"];
}
}
And then you could just call on the property AttemptCount wherever you need like so...
public void doEvent(object sender, EventArgs e)
{
AttemptCount.Add("Key1", "Value1");
}
You could make a property like this in your page:
protected Hashtable AttemptCount
{
get
{
if (Session["AttemptCount"] == null)
Session["AttemptCount"] = new Hashtable();
return Session["AttemptCount"] as Hashtable;
}
}
then you can use it without having to worry:
protected void Page_Load(object sender, EventArgs e)
{
this.AttemptCount.Add("key", "value");
}
test if it exists first
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if(Session["AttemptCount"] == null)
{
Session["AttemptCount"]=new Hashtable(); //Because of this line.
}
}
}
though the session_start is better, you only need to uses it on one page but you can create it for each session.
Hashtable hastable_name=new Hashtable()
Session["AttemptCount"]=hastable_name
Look at Global.asax and the Application_Started (I think) and there is one for session started too.