Access variable inside the tab page of the Form - c#

Here I'm facing problem,I'm adding form dynamically into tab page.
I have to get a static variable from that form.
i used code,but i can't get exact value which i need.
private void timer2_Tick(object sender, EventArgs e)
{
foreach (TabPage page in tabControl1.TabPages)
{
Control control = page.Controls[0];
if(!hyber.Form1.receiverflag)//bug line
{
tabControl1.TabPages.Remove(page);
}
}
}
In the above pic watch window
page.controls[0]
->[hyber.form1]
-->receiverflag
how to get that variable value.
Thanks in advance.

you are nor clear about bug line or in saying can't get the exact value you need.
if the variable is a public static bool it belongs to the class and not to the instance, being static, so when you write:
hyber.Form1.receiverflag
you are taking the variable's value regardless of the specific instance of Form1 you are dealing with, does not matter at all if you have created one instance and added to the TabPage, that variable always exists even if you do not create any instance.
if you are getting wrong/unexpected results could be, eventually, that another thread or another method has changed the value of that static field and this reflects everywhere in your application.
Edit: if it was not static, you could probably get what you are asking in this way:
var yourForm1 = (page.Controls[0] as hyber.Form1);
if( yourForm1 != null && !yourForm1.receiverflag)
{
....

Related

C# Delegate with Generic T as Button

I'm losing my mind trying to figure this out. I am developing a large windows application that requires all the controls in the main form to have their values updated in near real time. I moved the processing of this continuous method to its own thread, which in general is fine, but I knew that it required me to create a Delegate for setting my controls that were created in a different thread. However, I have a series of buttons that need to have the same various properties set for each one, but with different values. I was thinking I could setup a Delegate with a Generic type being Button, so I could simply pass in the proper button control when it is time to update its properties. But I am missing something, and it doesn't work:
//If this is wrong, please let me know
private delegate void SafeButtonText<T>(string value) where T : Button;
private void SetButtonTextSafe<T>(string value) where T : Button
{
//Using the generic Button passed in, set its values
if (T.InvokeRequired) //This doesn't compile
{
var d = new SafeButtonText<T>(SetButtonTextSafe<T>);
T.Invoke(d, new object[] { value }); //This doesn't compile
}
else
T.Text = value; //This doesn't compile
}
I thought I could use it like this (which doesn't seem possible)
SetButtonTextSafe<qualityButton>(values[0]);
If this is possible, or if there is a much better way of doing this, please feel free to tell me in detail. (if I can using this on a Button, I'd create another delegate for other control types as well)
Thanks in advance.
A type is just that...a type. You can't invoke an instance of it because you have no instance. It is merely reflected metadata.
You need to pass an instance of your button to your method.
private delegate void SafeButtonText<T>(T button, string value) where T : Button;
private void SetButtonTextSafe<T>(T button, string value) where T : Button
{
//Using the generic Button passed in, set its values
if (button.InvokeRequired) //This now compiles
{
var d = new SafeButtonText<T>(SetButtonTextSafe<T>);
button.Invoke(d, new object[] { value }); //This now compiles
}
else
button.Text = value; //This now compiles
}

Error message "An object reference is required for the non-static field, method or property."

I am creating a program to access a database.
The code that is causing me trouble is meant to open a new form when a button is pressed. It then gets data based on the selected values in a listbox on the main form and is needed to send that data to the second form to be placed in textboxes and labels.
The problem I have, is that in order for the code to execute without throwing the Error
"An object reference is required for the non-static field, method or property..."
I must make the method in the secondary form static; however this prevents me from accessing the controls on the secondary form.
Main Form Code Snippet:
private void MemView_Click(object sender, EventArgs e)
{
string selected = lstMember.SelectedItems[0].Text;
//MessageBox.Show(selected);
string[] data = P.selectMem(selected);
MessageBox.Show(data[0]);
MemForm mem = new MemForm(); //How to open a designed form
mem.Show(); //Displays the addmem form
MemForm.getData(data);
}
Secondary Form Code Snippet:
public void getData(string[] Data)
{
int index = 0;
bool loop = false;
string text;
while (loop == true)
{
if (index < 10)
{ text = "tb0" + index.ToString(); }
else
{ text = "tb" + index.ToString(); }
index = index + 1;
}
}
My secondary code snippet is meant to use the loop to fill all the data into the textboxes without me having to manually write out each tb00.Text = data[] etc.
I am unable to access the FindControls() method in C# most likely due to the need for a static method.
The P class used in the Main Form performs the SQL code and is working fully.
I've tried to give enough information for an answer, however if more is needed just ask in a comment I will try and provide more. :)
If getData() is a non-static method in MemForm, you need an instance of MemForm to use it. You have one: MemForm mem = new MemForm(); Use the mem object which is an instance of MemForm.
mem.getData(data);

Homework how to pass values from one form to an object in a list in another form

I have the following snippet of code that allows me to pull the properties from an object in my list and assign them to variables in other forms. However, I need to be able to pull the data from my variables in the other form and use those to set the properties of the given object.
My class Account is used to populate my list accounts. On my next form AccountMenu I have a class Variables1 that contains accessible variables that are used throughout the rest of my forms to keep track of the checking balance and saving balance. When logging off from the AccountMenu, I want to be able to pass the values from Variables1 to the account that was initially used.
I know how to pass variables from one form to another, but I'm not really sure how to update the form automatically, without a button, on the original form. Thus, the solution that I see is that I have a button on my AccountMenu form that "logs" the user out, via this.close(); Additionally, I guessed that under that button, I need to have some code that assigns the variables as properties to the object. I'm just not sure how I can access the set properties of the object, since it is dynamically called with the code below.
Can someone help me figure out what I need to do? Below is some of the relevant code so that you can see how I have things set up. I am just not sure how to access "matches" from the other form in order to update that specific object properties. Thank you, anyone, who can help!
//variable that will be used to check textbox1.Text
string stringToCheck;
//array of class Account
List<Account> accounts = new List<Account>();
public MainMenu()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//set value to user's input
stringToCheck = textBox1.Text;
//set a var that only returns a value if the .Name already exists
var matches = accounts.FirstOrDefault(p => p.Name == stringToCheck);
//check through each element of the array
if (matches == null)
{
accounts.Add(new Account(stringToCheck));
textBox1.Text = "";
label3.Visible = true;
}
else if (matches != null)
{
//set variables in another form. not sure if these are working
Variables1.selectedAccount = matches.Name;
//is this calling the CheckBalance of the instance?
Variables1.selectedCheckBalance = matches.CheckBalance;
//same thing?
Variables1.selectedSaveBalance = matches.SaveBalance;
//switch to form
AccountMenu acctMenu = new AccountMenu();
this.Hide();
acctMenu.Show();
}
}
As per my understanding I think what you required is kind of trigger on your parent form that needs to be called from your child application.
If that is what you required than you can go with defining an event on your AccountMenu form. and register this event from your Accounts form.
Than simply raise this event from your AccountMenu subform.
Deletegates and Events are really works like magic :)
Let me show you some code how to do this.
Code required in AccountMenu window:
public delegate void PassDataToAccounts(string result);
public event PassDataToAccounts OnPassDataToAccount;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (OnPassDataToAccount != null)
OnPassDataToAccount("result");
base.OnClosing(e);
}
Code required in Accounts window button1_Click event where the AccountMenu will open:
//set variables in another form. not sure if these are working
Variables1.selectedAccount = matches.Name;
//is this calling the CheckBalance of the instance?
Variables1.selectedCheckBalance = matches.CheckBalance;
//same thing?
Variables1.selectedSaveBalance = matches.SaveBalance;
//switch to form
AccountMenu acctMenu = new AccountMenu();
acctMenu..OnPassDataToAccount += childwindow_OnPassDataToAccount;
this.Hide();
acctMenu.Show();
}
void childwindow_OnPassDataToAccount(string result)
{
if (result == "result")
{
// Processing required on your parent window can be caried out here
//Variables1 can be processed directly here.
}
}

Why is the constructor invoked many times?

I am working on silverlight. I created a TextBox and when ever user changed any text in that it should show "*" at the top of file and which should disappear on clicking a save button.
My code works fine for one textbox but when i create second textbox (after the first one) then i found that constructor is invoked two times instead of one. And when i create third textbox(after the two) the constructor is invoked 3 times instead of one. (this textbox is created on a button click in my GUI dynamically which has some text written on it and when i make some change in that text then it shows "*" at top and which disappears on saving it).
Whereas i expect it to be invoked 1 time if i add 1 textbox at a time.
My code to do so is:
private bool modified;
public bool Modified
{
get { return modified; }
set { modified = value; OnPropertyChanged("Modified"); }
}
public ClassConstructor(AnotherClass pv)
{
MessageBox.Show("Number of call check");
setStar(false);
this.isModified = false;
}
private void setStar(bool modified)
{
Tab = this.FileName;
if (modified == false)
{
Tab += "";
}
else
{
Tab += " *";
}
Modified = modified;
}
public void TextChanged(object sender, TextChangedEventArgs e)
{
TextBox tb = (TextBox) sender;
setStar(!TextData.Equals(tb.Text));
}
public void SaveCode(object para)
{
TextData.txt = txt;
setStar(false);
}
Why this constructor is called so many times ? (I mean why my MessageBox for times if i create the fourth textbox) ?
A constructor creates one single instance of that class. So whenever you create a new instance (in your case a new TextBox) the constructor is called to create that object instance. This the sole purpose of constructor - To Be Called when you create an object of that class. Therefore the code inside that constructor is executed. Since you are showing MessageBox inside constructor, you are seeing it 5 times, for 5 new objects and 4 times for 4 new objects. As said in the wiki -
Instance constructors, sometimes referred to as .ctor, are used to
create and initialize any instance member variables when the new
expression is used to create an object of a class.
My first suggestion - Learn what a constructor is because unless you know what a constructor is, you will never understand why this happening. BTW, this is not the error, this is the feature of Object Oriented Programming that whenever you create a new instance, the constructor will be called.
A very good starting point will be here -
Constructor (object-oriented programming)

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