I am trying to make a method for change usercontrol when a button is clicked.
UserControl
namespace LogAnalyzer
{
public partial class UserSettings : UserControl
{
private static UserSettings _instance;
public static UserSettings Instance
{
get
{
if (_instance == null)
_instance = new UserSettings();
return _instance;
}
}
public UserSettings()
{
InitializeComponent();
}
private void btnUnpackPath_Click(object sender, EventArgs e)
{
flowLayoutPanel1.Hide();
}
}
}
My form
namespace LogAnalyzer
{
public partial class LogAnalyzerMain : Form
{
public LogAnalyzerMain()
{
InitializeComponent();
}
private void ChangeInstance(Control tab) {
if (!panelDisplay.Controls.Contains(tab))
{
panelDisplay.Controls.Add(tab);
tab.Dock = DockStyle.Fill;
}
tab.BringToFront();
}
private void btnSettings_Click(object sender, EventArgs e)
{
ChangeInstance(UserSettings);
}
}
}
It gives me an error in this line in my form ('UserSettings' is a type, which is not valid in the given context)
ChangeInstance(UserSettings);
You are passing the class itself but the method takes an instance of it, since you have a singleton property you could use that:
ChangeInstance(UserSettings.Instance);
Otherwise you had to store the instance somewhere, for example in the LogAnalyzerMain as field or if it's a control on your form you could use this.Controls.OfType<UserSettings>().First()
Related
I have a "MainForm" and a "GraphicsForm". Clicking "New" on the main form, a "GraphicsForm" will be created.
The problem is that when I create multiple "GraphicsForm", and when I want to save the content of one of the "GraphicsForm", I need to clicking "Save" on the "MainForm" and the program will save the content of the active "GraphicsForm" to a file, I don't know how to pass the content of this "GraphicsForm" to "MainForm" for storage.
MainForm.cs
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private ToolStripMenuItem _winMenuItem = new ToolStripMenuItem();
private GraphicsForm _graphicsForm;
private int _counter = 1;
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();
_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)
{
... // Problem here
}
private void Open_Click(object sender, EventArgs e)
{
... // Problem here
}
}
GraphicsForm.cs
public partial class GraphicsForm : Form
{
//StorageDoc is a class to manage all the graphics drawn by the user in the form.
private StorageDoc _storageDoc = new StotageDoc();
public GraphicsForm()
{
InitializeComponent();
}
private Canvas_MouseDown()
{
}
private Canvas_Paint()
{
}
...
Because MainForm is a MDI form, it is easy to use ActiveMdiChild to get the active child form.
class MainForm : Form
{
public void OnSaveButtonClick(object sender, EventArgs e)
{
if(ActiveMdiChild is GraphicsForm g)
Save(g);
}
}
I'm sure this has been answered before but basically, you pass in an instance of the 'data storage' to the new form.
interface ISaveForm
{
void Save();
}
class MainForm
{
private DataStorage _dataStorage;
private ICollection<ISaveForm> _forms = new List<ISaveForm>();
public void OnNew()
{
var subForm = new GraphicsForm(_dataStorage);
subForm.Show();
_forms.Add(subForm);
}
public void OnSave()
{
foreach(var form in _forms)
{
form.Save();
}
}
}
class GraphicsForm : Form,ISaveForm
{
private DataStorage _dataStorage;
public GraphicsForm(DataStorage dataStorage)
{
_dataStorage = dataStorage;
}
public void Save()
{
}
}
I have a problem with displaying UserControl on my Form.
The program in the nutshell:
In Form1 I have a button. After clicking this, in the Panel (container) my first UserControl (new.cs) are dynamically loaded.
On that panel I have another button that leads to another UserControl (choice.cs) and I want to display it in the same Panel (container) on my Form1.
The first point works good, but I have a problem with second one. I think I have to correct choice_button_Click function. Is there an easy way to do it?
Here is my code:
Form1.cs:
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void new_button_Click(object sender, EventArgs e)
{
if (!container.Controls.Contains(#new.Instance))
{
container.Controls.Add(#new.Instance);
#new.Instance.Dock = DockStyle.Fill;
#new.Instance.BringToFront();
}
else
{
#new.Instance.BringToFront();
}
}
public Panel getContainer()
{
return container;
}
}
}
new.cs:
namespace WindowsFormsApp1
{
public partial class #new : UserControl
{
private static #new _instance;
public static #new Instance
{
get
{
if (_instance == null)
_instance = new #new();
return _instance;
}
}
public #new()
{
InitializeComponent();
}
private void choice_button_Click(object sender, EventArgs e)
{
using (Form1 main = new Form1())
{
if (!main.getContainer().Controls.Contains(choice.Instance))
{
main.getContainer().Controls.Add(choice.Instance);
choice.Instance.Dock = DockStyle.Fill;
choice.Instance.BringToFront();
}
else
{
choice.Instance.BringToFront();
}
}
}
}
}
choice.cs:
namespace WindowsFormsApp1
{
public partial class choice : UserControl
{
private static choice _instance;
public static choice Instance
{
get
{
if (_instance == null)
_instance = new choice();
return _instance;
}
}
public choice()
{
InitializeComponent();
}
}
}
Your functional problem is that you aren't placing choice.Instance inside your instance of your Form1. You are creating a new form instead, placing it there, then discarding that form.
However, you also have an issue in your design, where you are violating the principal wherein a UserControl shouldn't be directly accessing and modifying its parent form. You would be better off adding an event to #new, raising that event from the button click, then handling that event in your form instance.
For example:
new.cs:
namespace WindowsFormsApp1
{
public partial class #new : UserControl
{
private static #new _instance;
public static #new Instance
{
get
{
if (_instance == null)
_instance = new #new();
return _instance;
}
}
public event EventHandler StepCompleted;
public #new()
{
InitializeComponent();
}
private void choice_button_Click(object sender, EventArgs e)
{
StepCompleted?.Invoke(this, EventArgs.Empty);
}
}
}
And Form1.cs:
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void new_button_Click(object sender, EventArgs e)
{
if (!container.Controls.Contains(#new.Instance))
{
container.Controls.Add(#new.Instance);
#new.Instance.Dock = DockStyle.Fill;
#new.Instance.BringToFront();
}
else
{
#new.Instance.BringToFront();
}
}
private void new_StepCompleted(object sender, EventArgs e)
{
if (!container.Controls.Contains(choice.Instance))
{
container.Controls.Add(choice.Instance);
choice.Instance.Dock = DockStyle.Fill;
choice.Instance.BringToFront();
}
else
{
choice.Instance.BringToFront();
}
}
}
}
Now you're obviously going to be working on the same form instance, since it itself is the one handling the event. Also, #new doesn't need to do any awkward lookup to find the proper Form1 instance and modify the form.
trying to get data from the main form to form 2. The main form has a textbox
and a button. when the button is pressed it opens form 2 which will display the data entered in the main form as a series of text blocks.
However I cant get the data to transfer between the forms. the code is bellow.
can anyone help or suggest anything I can do differently?
WPF 1 main form:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnOpenForm_Click(object sender, RoutedEventArgs e)
{
//btnset: Takes the values contained in the text boxes and updates
//the student class
//properties.
Student.sFname = firstname.Text;
Student.sSname = secondname.Text;
Window1 details = new Window1();
details.Show();
}
WPF 2 code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void details_Load(object sender, EventArgs e)
{
Fname.Text = Student.sFname;
Sname.Text = Student.sSname;
}
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
There are a number of ways to "pass data" between 2 classes. The easiest way is to expose property or method on Window1 and just set the text you need passed. Another way is to create a constructor on Window1 that takes in the data as parameters. Here is code that demonstrates these approaches.
public class Program
{
public static void Main(string[] args)
{
var c1 = new Class1();
c1.DoStuff();
}
}
public class Class1
{
public void DoStuff()
{
var c = new Class2("stuff");
var c2 = new Class2();
c2.AcceptStuff("stuff2");
c.Print();
c2.Print();
c2.MyData = "stuff3";
c2.Print();
}
}
public class Class2
{
private string _myData;
public Class2()
{
}
public Class2(string myData)
{
_myData = myData;
}
public string MyData
{
set { _myData = value;}
}
public void AcceptStuff(string myData)
{
_myData = myData;
}
public void Print()
{
Console.WriteLine(_myData);
}
}
Prints
stuff
stuff2
stuff3
I assume you have a class in MainWindow like:
`Public class Student
{
public static string sFname;
public static string sSname;
}`
When you click open button you are assigning values to those variable, but if you want to access them in another window mention the window name and then class name.
Check this code if its working?
`public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void details_Load(object sender, EventArgs e)
{
Fname.Text = MainWindow.Student.sFname;
Sname.Text = Mainwindow.Student.sSname;
}
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}`
I want to Use an instance of a class made in Form 1 in Form 2 (i changed it to a list for simplicity of example code:
Not only that, I want Form 2 to be able to modify it (Clear it at some point).
The advice I got was this, although I was not told how due to "no spoonfeeding allowed"
namespace automationControls.FileTime
{
public class Form_Main : Form
{
public List<string> folderList; //<---- i want to access this.....
private void button_showForm2_Click(object sender, EventArgs e)
{
Form_Log ConfirmBoxForm = new Form_Log(this);
ConfirmBoxForm.Show();
}
}
//form_Main opens form_Log
namespace automationControls.FileTime
{
public partial class Form_Log : Form
{
public Form_Log(Form_Main _f1)
{
InitializeComponent();
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
How.Do.I.AccessForm_Main.folderList.Clear();//<---- ............. in this function
}
}
}
Answered:In the constructor of Form_Log, store the reference to _f1 somewhere you can access it from elsewhere in Form_Log
Why don't you use the constructor that you have already added your form?
private Form_Main _mainForm;
public Form_Log(Form_Main _f1)
{
InitializeComponent();
_mainForm = _f1;
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
var myList = _mainForm.folderList;
}
Try This,
public class Form_Main : Form
{
public List<string> folderList; //<---- i want to access this.....
private void button_showForm2_Click(object sender, EventArgs e)
{
Form_Log ConfirmBoxForm = new Form_Log(this);
ConfirmBoxForm.Show();
}
}
Form log :
public partial class Form_Log : Form
{
private Form_Main _mainForm;
public Form_Log(Form_Main _f1)
{
InitializeComponent();
_mainForm = _f1;
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
_mainForm.folderList.Clear();
}
}
I don't know how advanced is your project but in this situation i would use delegates. Here is how i would do it:
public delegate void ModifyCollectionHandler(string parameter);
public delegate void ClearCollectionHandler();
public partial class Form1 : Form
{
public List<string> folderList;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2()
form.ClearItem+=form_ClearItem;
form.AddItem+=form_AddItem;
form.DeleteItem+=form_DeleteItem;
}
void form_DeleteItem(string parameter)
{
if (folderList == null)
return;
folderList.Remove(parameter);
}
void form_AddItem(string parameter)
{
if (folderList == null)
folderList = new List<string>();
folderList.Add(parameter);
}
void form_ClearItem()
{
if (folderList != null)
folderList.Clear();
}
}
public partial class Form2 : Form
{
public event ModifyCollectionHandler AddItem;
public event ModifyCollectionHandler DeleteItem;
public event ClearCollectionHandler ClearItem;
public Form2()
{
InitializeComponent();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (ClearItem != null)
ClearItem();
}
}
I hope I helped you :)
Best regards
in the Form1 put this :
public static List<string> folderList;
you can simply call it from any form ex:Form2 like this :
From1.folderList.Clear();
I created a splash class with a timer on it, and when the timer is finished it instances another class as shown in the code below. When i then create a new class how can i access MainWindow?
namespace Kinetics
{
public class KineticsCommand : RMA.Rhino.MRhinoCommand
{
Splash Splash = new Splash();
Splash.Show();
}
public partial class Splash : Form
{
public Splash()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Close();
MainUI MainWindow = new MainUI();
MainWindow.Show();
}
}
public class CustomEventWatcher : MRhinoEventWatcher
{
public override void OnReplaceObject(ref MRhinoDoc doc, ref MRhinoObject old, ref MRhinoObject obj)
{
// How can i access the class from here?
}
}
}
CustomEventWatcher will need a reference to MainWindow, for example via a property within CustomEventWatcher:
public class CustomEventWatcher : MRhinoEventWatcher
{
MainUI _mainUI = null;
public MainUI MainWindow { get { return _mainUI; } set { _mainUI = value; } }
public override void OnReplaceObject(ref MRhinoDoc doc, ref MRhinoObject old, ref MRhinoObject obj)
{
if(_mainUI != null)
_mainUI.Whatever();
}
}
public partial class Splash : Form
{
public Splash()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Close();
MainUI MainWindow = new MainUI();
CustomEventWatcher cew = new CustomEventWatcher();
cew.MainWindow = MainWindow;
MainWindow.Show();
}
}
You need to have MainWindow as an instance or static variable, not a method variable. This will allow it to be accessed from multiple classes, as long as its marked as public.
use a static factory method or property (Property shown below).
New EDITED VERSION w/SIngleton:
namespace Kinetics {
public class KineticsCommand : RMA.Rhino.MRhinoCommand
{
Splash splashVariable= Splash.SingletonInstance;
splashVariable.Show();
// or, combine and just write...
Splash.SingletonInstance.Show();
}
public partial class Splash : Form
{
private Splash splsh;
private Splash()
{
InitializeComponent();
}
public static Splash SingletonInstance // Factory property
{
get { return splsh?? (splsh = new Splash()); }
}
// Factory Method would be like this:
public static Splash GetSingletonInstance() // Factory method
{
return splsh?? (splsh = new Splash());
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Close();
MainUI MainWindow = new MainUI();
MainWindow.Show();
}
}
public class CustomEventWatcher : MRhinoEventWatcher
{
public override void OnReplaceObject(ref MRhinoDoc doc,
ref MRhinoObject old, ref MRhinoObject obj)
{
// to access the instance of the class from here, now
// all you need to do is call the static factory property
// defined on the class itself.
Splash.SingletonInstance.[Whatever];
}
}
OLD Version, using the Splash variable: Wherever you call the method, pass that variable to it.
namespace Kinetics {
public class KineticsCommand : RMA.Rhino.MRhinoCommand
{
Splash splashVariable= new Splash();
splashVariable.Show();
}
public partial class Splash : Form
{
public Splash()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Close();
MainUI MainWindow = new MainUI();
MainWindow.Show();
}
}
public class CustomEventWatcher : MRhinoEventWatcher
{
public override void OnReplaceObject(ref MRhinoDoc doc,
ref MRhinoObject old, ref MRhinoObject obj,
Splash splashScreen)
{
// to access the instance of the class from here,
// pass in the variable that holds a reference to the instance
splashScreen.[Whatever];
}
}