I have one form in my software that is displaying the total value (it is a label), and I want to display the value of that label on another form.
Here is my code:
public void PresmetajTotal()
{
for (var i = 0; i < dataGridView1.Rows.Count; i++)
{
vkp += Convert.ToInt64(dataGridView1.Rows[i].Cells[4].Value);
lblTotal.Text = vkp.ToString();
}
}
And on the other form I created this:
private void Change_Load(object sender, EventArgs e)
{
Prodazba prodaz = new Prodazba();
label4.Text = prodaz.lblTotal.Text();
}
The error i get is :
CS0122 'Prodazba.lblTotal' is inaccessible due to its protection level
Add a public property in Prodazba form that will return the value of the label.
public partial class Prodazba()
{
public string Total { get { return lblTotal.Text; } }
//....
}
Then access it like:
private void Change_Load(object sender, EventArgs e)
{
Prodazba prodaz = new Prodazba();
label4.Text = prodaz.Total;
}
Tw things:
You are creating an new form with new Prodazba()
Your label is private
The second one is easier to deal with. In the form editor, or your designer code, set the access level to internal or public.
For the first one, you could take several approaches depending on how the forms are created. If your first form loads the Prodazba, you could:
public partial class YourMainForm
{
Prodazba prodaz;
then...
private void Change_Load(object sender, EventArgs e)
{
prodaz = new Prodazba();
prodaz.Load += delegate {this.label4.Text = prodaz.Total};
prodaz.Show();
}
If your label is internally accessable, you could run any event handler from it, like prodaz.label4.TextChanged += ...
Related
There are two forms, a MainForm and a GraphicsForm.
In MainForm, there are "New" and "Save", "Open" buttons. When clicking the "New", a GraphicsForm created (When the "New" is clicked multiple times, multiple GraphicsForms are created).
The question is, when created multiple GraphicsForms, and the user only wants to save the content in one of them or open a content file to one of them, How to implement this?
MainForm.cs
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private ToolStripMenuItem _winMenuItem = new ToolStripMenuItem();
private GraphicsForm _graphicsForm;
private int _counter = 1;
private ContentDoc _contentDoc = new ContentDoc();
private void New_Click(objec sender, EventArgs e)
{
_winMenuItem.Name = "Win";
_winMenuItem.Text = "Windows";
int item = MainMenuStrip.Items.IndexOf(_winMenuItem);
if (item == -1)
{
MainMenuStrip.Items.Add(_winMenuItem);
MainMenuStrip.MdiWindowListItem = _winMenuItem;
}
_graphicsForm = new GraphicsForm(_contentDoc);
_graphicsForm.Name = string.Concat("Win_", _counter.ToString());
_graphicsForm.Text = _graphicsForm.Name;
_graphicsForm.MdiParent = this;
_graphicsForm.Show();
_graphicsForm.WindowState = FormWindowState.Maximized;
_counter++;
}
private void Save_Click(object sender, EventArgs e)
{
... // here
}
private void Open_Click(object sender, EventArgs e)
{
... // here
}
}
GraphicsForm.cs
public partial class GraphicsForm : Form
{
//ContentDoc is a class to manage all the graphics drawn by the user in the form.
private ContentDoc _contentDoc = new ContentDoc();
public GraphicsForm(ContentDoc contentDoc)
{
InitializeComponent();
_contentDoc = contentDoc;
}
private Canvas_MouseDown()
{
}
private Canvas_Paint()
{
}
...
The parent form has an ActiveMdiChild property, so you can use the to access the currently-selected GraphicsForm instance:
var activeGraphicsForm = ActiveMdiChild as GraphicsForm;
There are other variations you might use, e.g. pattern matching, depending on the specific details and your preference.
You can then put your saving logic in a public method in GraphicsForm and call it from the parent form. Alternatively, you can put your saving logic in the parent form and expose the data to be saved via one or more public properties in GraphicsForm.
Hi members,
I have a simple question about how to pass data to Page from MainWindow.
I searched on google/ and here... But I am not found exact answer.
I would like modify, change the Page1( SW_GUI.xaml) elements such as label content, or later change other GUI element content.
However I only can reached (myself) this way: firstly make change on label of SW_GUI.xaml and then create instance of this Page(SW_GUI.xaml) and load in a frame of MainWindow content.
But if this Page loaded once, I cannot modify /update a label automatically, without loading the SW_GUI Page again into the frame.
You can find the very simple and initial code below.
MainWindow.xaml.cs file
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// ACTION one - just try reason
SW_GUI sW_GUI = new SW_GUI();
sW_GUI.RESULT_MAKER(true);
CenterFrame.Content = sW_GUI;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// ACTION two - just try reason
SW_GUI sW_GUI = new SW_GUI();
sW_GUI.RESULT_MAKER(false);
CenterFrame.Navigate(sW_GUI);
}
}
-----------------
PAGE1 aka SW_GUI
SW_GUI.xaml.cs file
public partial class SW_GUI : Page
{
public SW_GUI()
{
InitializeComponent();
}
public void RESULT_MAKER ( bool results)
{
if (results==true)
{
RESULT_BOX.Background = new SolidColorBrush(Color.FromRgb(0, 245, 95));
RESULT_BOX.Text = "(PASS)";
}
else
{
RESULT_BOX.Background = new SolidColorBrush(Color.FromRgb(245, 53, 0));
RESULT_BOX.Text = "(FAIL)";
}
}
}
SHORT logic: Button_Click on mainwin call the sW_GUI.RESULT_MAKER method and make very simple change on a label. Then, I load the sW_GUI instance into the CenterFrame.Content.
QUESTION: Ca you provide a little guide or give a simple example what I have to add, change to achieve that I don't need to load the page into the frame each case when I want to update a label content etc.
Many thanks for it.
Hello I have made a small sample in MainWindow.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private SW_GUI SW_GUIPage = new SW_GUI();
private void ActivateSW_GUI(bool SetResult)
{
SW_GUI SW = SW_GUIPage;
SW.RESULT_MAKER(SetResult);
if (!(CenterFrame.Content is SW_GUI))
{
CenterFrame.Content = SW_GUIPage;
}
}
int ActionSetter = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (ActionSetter == 0)
{
ActivateSW_GUI(true);
ActionSetter = 1;
}
else if (ActionSetter == 1)
{
ActivateSW_GUI(false);
ActionSetter = 0;
}
}
}
For example if I have a form called frmOne and I am there and I do some things then click a button event and it goes and takes me to a second form called frmTwo. Then I am in frmTwo and I do some things then I click a button in frmTwo and this button creates a new instance of frmOne. Since now I have two forms of frmOne open what will Visual Studios call the second instance of frmOne. I need to figure this out because I need to access it in code. I have tried using frmOne as the name to reference it in code but it doesnt work on the second instance. Any ideas how I can find this name or what Visual Studios calls it? I am assuming Visual Studios does something like calling the second instance frmOne1 or something like that. Thanks in advance.
From the example above here below frmShoppingCart is my first form. I have two instances of it open. I am trying to close the second instance from the closing event of another form. I can close the first instance with the code below and I can use it to close the second instance if I knew what the name was of the second instance which I am assuming is different from frmShoppingCart. I just am assuming Visual Studios is calling the name of my second instance of frmShoppingCart something else than frmShoppingCart.
private void frmViewer_FormClosing(object sender, FormClosingEventArgs e)
{
//close shopping cart form and refresh and open the shop now form
frmShoppingCart obj = (frmShoppingCart)Application.OpenForms["frmShoppingCart"];
obj.Close();
}
It's not clear why you need to reference a form indirectly by name. You could instead hold a reference directly to the form.
If you still want to reference by name, you can, but you need some other piece of data to disambiguate the form as #Steve said in the comments. To do that you could add another property to the form. Here's a small demo form
public partial class Form1 : Form
{
public Form1() => InitializeComponent();
private void button1_Click(object sender, EventArgs e)
{
var f = new Form1 { Instance = ++Counter };
f.ShowDialog();
}
private void button2_Click(object sender, EventArgs e)
{
var forms = Application.OpenForms;
}
public int Instance { get; set; }
public static int Counter { get; set; }
}
that shows, under the debugger with a breakpoint after
var forms = Application.OpenForms;
that you can see the disambiguation.
Note that searching by name alone will return the first form with that name. To get the correct one, do a search using linq against Application.OpenForms (again, credit #Steve):
var myForm = Application.OpenForms
.FirstOrDefault(x => x.Name == "Form1" && x.Instance == 1);
This is but one way to find the form. You could instead change Name when you create the form. Here's an example using the Counter above.
private void button1_Click(object sender, EventArgs e)
{
var f = new Form1();
f.Name += ++Counter;
f.ShowDialog();
}
This gives us
You can use Singleton to have a list of named Forms opened from the first ...
public partial class Form1 : Form {
public FormsOpened Forms => FormsOpened.Instance;
public Form1() {
this.InitializeComponent();
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
for (int i = 0; i < 10; i++) {
var f = default(Form);
// Form2 is a simple empty form
this.Forms.formsOpened.Add(f = new Form2() { Name = "Pippo" + i });
f.Show();
}
}
protected override void OnClosing(CancelEventArgs e) {
base.OnClosing(e);
foreach (var f in this.Forms.formsOpened) {
f.Close();
}
}
}
public sealed class FormsOpened {
private static FormsOpened instance = null;
public List<Form> formsOpened = new List<Form>();
private int counter = 0;
public static FormsOpened Instance {
get {
if (instance == null) {
instance = new FormsOpened();
}
return instance;
}
}
private FormsOpened() {
this.counter++;
}
}
In this way in every class you want you can access the FormsOpened Forms => FormsOpened.Instance and use it ;)
I am currently making some basic incremental game in c# in WFA. Here's the code:
namespace Xadrs
{
public partial class Form1 : Form
{
public void Ref()
{
label2.Text = Points.ToString();
button2.Text = "Level up! (" + Upgradeprice.ToString() + ")";
label4.Text = Upgrade.ToString();
label6.Text = Upgradeautoclick.ToString();
button4.Text = "Level up PPS! (" + Upgradeautoclickprice.ToString() + ")";
}
public int ach_beginner = 0;
public int ach_intermediate = 0;
public int ach_expert = 0;
public int ach_master = 0;
int Points = 0;
int Upgrade = 1;
int Upgradeautoclick = 0 ;
int Upgradeautoclickprice = 110;
int Upgradeprice = 25;
public Form1()
{
InitializeComponent();
Ref();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (Upgrade == 5)
{
Points++;
Ref();
}
}
private void button1_Click(object sender, EventArgs e)
{
Points += Upgrade;
Ref();
}
private void button2_Click(object sender, EventArgs e)
{
if (Points >= Upgradeprice)
{
Upgrade += 1;
Points -= Upgradeprice;
Upgradeprice += Upgradeprice / 4;
}
else
{
MessageBox.Show("Not Enough Nico points...");
}
Ref();
if (Upgrade == 5)
{
MessageBox.Show("Beginner: Reach 5 PPS.\nReward: AutoClick!", "ACHIEVEMENT UNLOCKED!");
ach_beginner = 1;
timer1.Enabled = true;
Upgradeautoclick = 1;
button4.Visible = true;
Ref();
}
}
Form2 achievements = new Form2();
private void button3_Click(object sender, EventArgs e)
{
Form2.Show();
}
private void button4_Click(object sender, EventArgs e)
{
if (Points >= Upgradeautoclickprice)
timer1.Interval = timer1.Interval / 2;
Points -= Upgradeautoclickprice;
Upgradeautoclickprice += Upgradeautoclickprice;
}
and in form2 I want to have:
if (ach_beginner = 1)
{
//Text in this label = something like: Beginner - Reach 5 Points per click
labelwithachievement.Visible = true;
}
but the ach_beginner isn't declared in form2. I would like to somehow "connect" this integer to have its declaration from form1 in form2.
Don't think of it as sharing the integer itself, instead think of it as Form2 has a dependency on something in Form1.
Since the variable is currently public (we'll get to that in a minute), at the simplest all you need to do is provide Form2 with a reference to the instance of Form1. Put a property on Form2 and require a value in its constructor:
private Form1 form1Instance;
public Form2(Form1 form1)
{
this.form1Instance = form1;
}
Then when you create an instance of Form2, pass it a reference to the current instance of Form1:
Form2 achievements = new Form2(this);
Then in Form2 you can refer to its new member variable to get information from Form1:
if (this.form1Instance.ach_beginner == 1)
Note regarding public variables... It's generally considered best practice to expose properties publicly instead of variables. So replace this:
public int ach_beginner = 0;
with this:
public int Ach_Beginner { get; set; }
And update references to it accordingly. There are a variety of reasons for this, but ultimately the idea is that a class should hide its values and provide access to them rather than just provide the values themselves.
This is a pretty simple start to the idea of providing a dependency to an object, and there are a number of places you can go from here. For example, if you don't want to pass around entire forms as dependencies (since they include considerably more data/functionality than is otherwise needed for the dependency), you can encapsulate your values in an object of their own and pass around that object as the dependency.
Extrapolating from there, you can continue to separate business logic from UI elements (like forms and controls), and begin to move your logic into those business logic objects and components. This will make your logic more portable onto other UI platforms, easier to test, etc.
For example, suppose you have a class such as:
public class LevelInfo // guessing on an appropriate name here
{
public int Ach_Beginner { get; set; }
public int Ach_Intermediate { get; set; }
public int Ach_Expert { get; set; }
public int Ach_Master { get; set; }
}
Then in Form1 you use that object instead:
private LevelInfo levelInfo = new LevelInfo();
// elsewhere...
levelInfo.Ach_Beginner = 1;
// etc.
Then Form2 can require a reference to that object:
private LevelInfo levelInfo;
public Form2(LevelInfo level)
{
this.levelInfo = level;
}
and use that object:
if (this.levelInfo.Ach_Beginner == 1)
At this point LevelInfo is de-coupled from the UI and can contain portable business logic/information.
All you need is a Parameter. You call the Form2.Show Method. As any other Method a method of Form2 can become a parameter. So in Form2 you could do the following:
public void Show(int ach_beginner)
{
//Do sth. with your int
this.Show();
}
If you call Form2 on Form1 now you can pass your integer:
private void button3_Click(object sender, EventArgs e)
{
Form2.Show(ach_beginner);
}
I think this is the easiest approach. Instead of overriding the Show Method you could make a Property as well. In Form2 declare:
public int AchBeginner {get;set;}
In Form1 you set this value before you call the Show Method:
private void button3_Click(object sender, EventArgs e)
{
Form2.AchBeginner = ach_beginner;
Form2.Show();
}
As David explained in comments, the value won't be updated on Form2. If you want to achieve this you could use an Interface:
public interface IBeginner
{
int AchBeginner{get;set;}
}
public void Form1 : Form, IBeginner
{
public int AchBeginner{get;set;}
//The place you create Form2
Form2.Beginner = this;
}
public void Form2 : Form
{
public IBeginner Beginner{get;set;}
//Here you can access
int achBeginner = Beginner.AchBeginner:
}
UPDATE
Based on the comment from the question author i think an event would be the most usefull think. So you can tell your Form2 that your character on Form1 reaches level 5. For example:
public class LevelEventArgs : EventArgs
{
public int Level {get;}
public LevelEventArgs(int level)
{
Level = level;
}
}
//Form1 need to implement an Event which later can notify any subscriber (Form2 in this case)
public class Form1 : Form
{
public event EventHandler<LevelEventArgs> LevelUp;
//When your character reach new level do following:
LevelUp?.Invoke(this, new LevelEventArgs(ach_beginner));
//Show Form2
Form2 form = new Form2(this);
form.Show();
}
Form2 needs to subscribe this event now. For this you need to put Form1 to Form2 (or better an Interface as described above)
public class Form2 : Form
{
public Form2(Form form1)
{
//Register Event LevelUp from Form1
form1.LevelUp += (args) =>
{
if (args.Level == 5)
//Level 5 reached
}
}
}
I have 2 forms. The second form is opened from a method in the first form and I wish to be able to update the textbox that exists within that second form.
Basically I have the following code:
private void sendAllButton_Click(object sender, EventArgs e)
{
SendConsoleGUI sendOutGUI = new SendConsoleGUI();
sendOutGUI.Show();
sendOutGUI.sendConsoleTextBox.Text = "Test";
}
When I press the button the second form (SendConsoleGUI form) opens but "Test" is never added to its textbox.
Am I doing something wrong here?
You need to use invoke method.
sendOutGUI.Invoke((MethodInvoker) delegate { sendOutGUI.sendConsoleTextBox.Text = "Test"; });
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void sendAllButton_Click(object sender, EventArgs e)
{
SendConsoleGUI sendOutGUI = new SendConsoleGUI("Test");
sendOutGUI.Show();
}
}
public partial class ChildForm : Form
{
public ChildForm(string str)
{
InitializeComponent();
sendConsoleTextBox.Text = str;
}
}
This will work for you if you only wish to update it when the ChildForm is initially created.