C# - Possible of getting MDI parent through Application? - c#

This is my MDI Parent.
public partial class frmMain : Form
{
public Options options {get; set;}
public Project project {get; set;}
public frmMain()
{
InitializeComponent();
}
}
My MDI child below need to access the project and option.
public partial class frmInput : form
{
public frmInput(frmMain parent)
{
InitializeComponent();
this.MdiParent = parent;
//Of course I can do this
Options options = ((frmMain) this.MdiParent).options;
//But if I can have something as following, I can have
//a static method to access options in the frmMain anywhere.
frmMain mainform = Application.MainForm;
Options options = mainform.options;
}
}
If Application doesn't provide the access to the MdiParent, any other means that we can access it through static method?

Why don't you manually create a static field to do so? Something like:
public class frmMain {
public static frmMain ApplicationMainWindow {get; private set;}
public frmMain() {
ApplicationMainWindow = this;
InitializeComponent();
}
}
Other than that Application.OpenForms returns all open forms for the application and you can look it up to find the frmMain instance. It's a less than ideal solution though.

This would work fine:
public partial class frmInput : form
{
private frmMain mainFrame;
public frmInput(frmMain parent)
{
mainFrame = parent;
InitializeComponent();
this.MdiParent = parent;
//Of course I can do this
Options options = mainFrame.options;
}
private void Something() {
Options o = mainFrame.options; //can access options now.
}
}
There's maybe more OO approaches that could be applied to decomple these classes though.

Related

C#: Referencing an instance of a class that was made in another class

I need some help with C#.
Let's say I have 3 classes. MainMenu, Form1 and Data.
I have created an instance of Data (referenced as StoreData) in MainMenu.
public partial class MainMenu : Form
{
public Data StoreData = new Data();
}
I want to be able to access this instance of StoreData in Form1. How do I reference it or import it?
You can either
Make StoreData static 🤮 in a static class MyAWesomeStatic and call MyAWesomeStatic.StoreData or even in MainMenu class iteself.
Pass a reference of StoreData to Form1 either via the constructor or a property when you create it.
or pass a reference of MainMenu to form1 and call mainMenu.StoreData when needed.
However, another option might be to use Dependency Injection (DI) and Loosely Couple all this. Have a Singleton instance and pass the in-memory Data Store as some sort of Service (which is what the cool kids might do).
Update
Sorry, still at the beginning stages of learning C#. What does it mean
to make a class static?
Given your current level of knowledge and all-things-being-equal, i think the easiest approach might be just pass in a reference
public class Form1
{
public Data StoreData { get; set; }
}
...
var form = new Form1();
form.StoreData = StoreData;
form.Show();
If you want to reference one class within another class (and don't want to make anything static), composition is one way to go.
You want to reference field of MainForm in Form1, so you want to reference MainForm itself. Thus, you need to create field in Form1 of MainForm type:
public class Form1 : Form
{
...
public MainForm mf { get; set; }
...
}
Now, you can access StordeData with mf.StordeData within Form1.
You could make StoreData static in a static class, something like this:
public static class Form1
{
public static Data StoreData { get; set; }
}
Suppose your StoreData class have one property
public class StoreData
{
public int MyProperty { get; set; }
}
Add static property to your mainform.cs and assign value to MyProperty = 1
public partial class MainMenu : Form
{
public static StoreData Data { get; set; } //static property
private void MainMenu_Load(object sender, EventArgs e)
{
Data = new StoreData { MyProperty = 1 };
}
}
And access your StoreData property inside Form1.cs like
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
var id = MainMenu.Data.MyProperty;
}
}
Try once may it help you
Result:

Access Application.MainWindow content in usercontrol

In WPF application it is easy to access MainWindow content but how to do in usercontrol.
In WPF Application, if my MainWindow name is Window1 and i have to access its one of the string variable named CName from some other class in same application.
Window1 ww = Application.Current.MainWindow as Window1;
String reqstring = ww.CName ;
I want to do same thing in usecontrol too.
Assume my usercontrol name is ABCcontrol and first/main Class name is ABCconrolLib
namespace ABCcontrol
{
public partial class ABCcontrolLib : UserControl
{
Public String CName = "ABC";
//....
}
}
Now i want to access this CName in some other class of same usercontrol by using Application.Control.MainWindow or by some other similar way
Please help me out as this is my first UserControl in WPF
You can access Application.Current.MainWindow because you have just one instance of MainWindow in your whole application so they defined it as a static property.
If you have the same characteristic for your users control (just you need to use a single instance of it in the whole application) you can define a static property there as well.
Something like :
then you can access name property like UserControl1.Instance.CName
public partial class UserControl1 : UserControl
{
public static UserControl1 Instance
{
get;
private set;
}
Public String CName = "ABC";
public UserControl1()
{
if (Instance != null)// there should be just one instance
throw new NotSupportedException();
Instance = this;
InitializeComponent();
}
}
if you get error then you do not have just one instance of your usercontrol, you have to define a List and register each instance of your users controls there. Something like:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
(App.Current as App).UserControl1List.Add(this);
InitializeComponent();
}
}
public partial class App : Application
{
public App()
{
UserControl1List = new List<UserControl1>();
}
public List<UserControl1> UserControl1List
{
get;
private set;
}
}
then you can reach to each instance like (App.Current as App).UserControl1List[0]...
or you can use a dictionary for storing each UserControl there.

Using and instance of a class on two forms

I am struggling to get my head around the following.
I current have three forms, my main and one main class.
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
}
public partial class frmSuppliers : Form
{
public frmSuppliers()
{
InitializeComponent();
}
}
public partial class frmCustomers : Form
{
public frmCustomers()
{
InitializeComponent();
}
}
In my main program I have:
public class Program
{
public StockControl StockSystem = new StockControl("The Book Shop", 20);
}
I want to be able to access the methods from StockControl in frmSuppliers and frmMain.
I know this may be a N00b question - but its been bugging me all day!
You need to pass it to the other forms as a constructor parameter, then store it in a private field.
declare it static
public static StockControl StockSystem = new StockControl("The Book Shop", 20);
and use as
Program.StockSystem
You should add a field of type StockControl to each of your forms, and make it public, or add getter/setter to it. This means adding the following lines to each one of your forms:
private StockControl _stockCtrl;
public StockControl StockCtrl
{
get { return _stockCtrl; }
set { _stockCtrl = value; }
}
The in the cod of each form you can access your StockControl. But it will be empty (i.e. null) if you don't assign it something. This is something I'd do before opening the form. If you are in your main method:
frmSuppliers frmToOpen = new frmSuppliers();
frmSuppliers.StockCtrl = StockSystem;
frmSuppliers.Show();

How to update a control in MDI parent form from child forms?

I looked to some similar questions but I didn't really get my answer, so I ask again hopefuly someone can explain it.
The situation:
I have a MDI form that has some menues and a status bar and stuff like that. Is the only way of altering text for status bar and doing other things to the parent form is to call it as static? Or if not, can you please give an example for updating (for example) status bar that exist in parent form within the child forms?
Thanks!
You need to make the child forms take a parent form instance as a constructor parameter.
The children can save this parameter to a private field, then interact with the parent at will later.
For optimal design, you should abstract the parent from the child through an interface implemented by the parent, containing methods and properties that do what the children need. The children should then only interact with this interface.
public interface IChildHost {
void UpdateStatusBar(string status);
//Other methods & properties
}
public partial class ParentForm : IChildHost {
public void UpdateStatusBar(string status) {
...
}
//Implement other methods & properties
}
public partial class ChildForm {
readonly IChildHost host;
public ChildForm(IChildHost parent) {
this.host = parent;
}
}
The Form class already exposes a property MdiParent ensure the parent forms IsMdiContainer property is set accordingly.
Another option is to use events (you can build these events into a base class and let all your child forms inherit from it):
// Code from Form 1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 objForm2 = new Form2();
objForm2.ChangeStatus += new ChangeStatusHandler(objForm2_ChangeStatus);
objForm2.Show();
}
public void objForm2_ChangeStatus(string strValue)
{
statusbar.Text = strValue;
}
}
// Code From Form 2
public delegate void ChangeStatusHandler(string strValue);
public partial class Form2 : Form
{
public event ChangeStatusHandler ChangeStatus;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (PassValue != null)
{
PassValue(textBox1.Text);
}
}
}

C# Trying to access the location of a panel's parent

I have a main form with a tab control on it. The tabs get populated by adding panels from other forms within the solution. One of these panels has some code that will pop up an options window. I want that window to align itself to the top right hand side of the main form. To do this I need the location and size of the main form. However, I cannot seem to access any property that will tell one of the panels what the location of that main form is.
I've tried things like this.Parent, this.ParentForm and this.GetContainerControl(). They all return null.
Any ideas?
Addendum
//Code for the main form:
namespace WinAlignTest {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
tabControl1.TabPages[0].Controls.Add(new SomeApplication().panel1);
}
}
}
//Code that shows the option window
namespace WinAlignTest {
public partial class SomeApplication : Form {
private ApplicationOptions Options;
public SomeApplication() {
InitializeComponent();
Options = new ApplicationOptions();
}
private void button1_Click(object sender, EventArgs e) {
Options.Show();
//This will always move the location to {0,0}
Options.Location = new Point(base.Location.X,base.Location.Y);
}
}
}
I'm confused, you seem to be adding a panel which belongs to SomeApplication to Form1. I would suggest you actually make SomeApplication a UserControl instead of a form:
//Code for the main form:
namespace WinAlignTest {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
tabControl1.TabPages[0].Controls.Add(new SomeApplication());
}
}
}
//Code that shows the option window
namespace WinAlignTest {
public partial class SomeApplication : UserControl {
private ApplicationOptions Options;
public SomeApplication() {
InitializeComponent();
Options = new ApplicationOptions();
}
private void button1_Click(object sender, EventArgs e) {
Options.Show();
// You might need to use PointToScreen here
Options.Location = this.Location;
}
}
}
Check out
Application.OpenForms
That should give you access to what you want.
the base identifier accesses a parent element.
Two possible problems: First, your constructors don't explicitly extend your base constructor. it would look like this:
public Form1():base(){}
I still recommend making getter methods in the Form1 class. It would look something like this:
public int Form1Location
{
get{return /*FormLocation*/}
}
and call it from WinAlignTest
Let me know if this works.

Categories