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.
Related
I wanted to load a user control to a panel with a button, but when I tried this code it shows nothing. I wonder if there is a solution for my problem because I've already tried many solutions from internet but nothing worked.
this is my code :
on user cotrol
public partial class UserControl1 : UserControl
{
public static UserControl1 _instance;
public static UserControl1 Instance {
get {
if (_instance == null)
_instance = new UserControl1();
return _instance;
}
}
public UserControl1()
{
InitializeComponent();
}
}
on winform by button click
private void b1_Click(object sender, EventArgs e)
{
if (!panel5.Controls.Contains(UserControl1.Instance))
{
panel5.Controls.Add(UserControl1.Instance);
UserControl1.Instance.Dock = DockStyle.Fill;
UserControl1.Instance.BringToFront();
}
else
UserControl1.Instance.BringToFront();
}
main form
user control
Thanks for your concern.
try this.
Hope this will help .you
private void set2ControlTopanel(control f) {
try {
p2Form = f;
p2Form.Dock = DockStyle.Fill;
p2Form.Show();
panelTop.Controls.Add(p2Form);
p2Form.BringToFront();
}
catch (Exception ex) {
MsgBox(ex.Message);
}
}
I have a MainForm which has a panel. I have added a UserControl1 in it while start the application. by clicking a button inside of UserControl1 trying to call UserControl2 to add the panel and clear UserControl1 from main form panel. Then by clicking second button inside of UserControl2 trying to call UserControl1 and clear UserControl2 from main forms panel. But in my code when I call UserControl2 MainForm comes blank. what is the problem? here is code:
namespace UserControlTest
{
public partial class MainForm : Form // main from
{
private static MainForm _instance;
public static MainForm Instance
{
get
{
if (_instance == null)
{
_instance = new MainForm();
}
return _instance;
}
}
public MainForm()
{
InitializeComponent();
if (!panel1.Controls.Contains(UserControl1.Instance)) // checking UserControl1 existance
{
panel1.Controls.Add(UserControl1.Instance); // add
UserControl1.Instance.Dock = DockStyle.Top; // dock it
UserControl1.Instance.BringToFront(); // bring to front of panel1
}
}
public void CallUserControl1() // method helps to bring UserControl1 to front of panel 1
{
if (!panel1.Controls.Contains(UserControl1.Instance))
{
panel1.Controls.Clear();// clearing controls
panel1.Controls.Add(UserControl1.Instance);
UserControl1.Instance.Dock = DockStyle.Top;
UserControl1.Instance.BringToFront();
}
else
{
UserControl1.Instance.BringToFront();
}
}
public void CallUserControl2()// method helps to bring UserControl2 to front of panel 1
{
if (!panel1.Controls.Contains(UserControl2.Instance))
{
panel1.Controls.Clear();// clearing controls
panel1.Controls.Add(UserControl2.Instance);
UserControl2.Instance.Dock = DockStyle.Top;
UserControl2.Instance.BringToFront();
}
else
{
UserControl2.Instance.BringToFront();
}
}
}
}
// first user control which helps to call UserControl2 to come front page
public partial class UserControl1 : UserControl
{
private static UserControl1 _instance;
public static UserControl1 Instance
{
get
{
if (_instance == null)
{
_instance = new UserControl1();
}
return _instance;
}
}
public UserControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MainForm mainForm = new MainForm();
mainForm.CallUserControl2();
}
}
// second user control which helps to call UserControl1 to come front page
public partial class UserControl2 : UserControl
{
private static UserControl2 _instance;
public static UserControl2 Instance
{
get
{
if (_instance == null)
{
_instance = new UserControl2();
}
return _instance;
}
}
public UserControl2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MainForm main = new MainForm();
main.CallUserControl1();
}
}
Update: Thanks to comment of #RonBeyer this is worked but needed to clear controls of panel first than
var main = this.FindForm() as MainForm;
main.CallUserControl1();
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()
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 wants to access Form1's EventHandler In Form2
Form1 EventHandler is:-
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
How to achieve it?.
You are doing something wrong.
If you want to expose functionality, you should create a public method/function to do so. You can call this from your event handler and from your other form.
Answer updated by your question in comment, I didn't checked that it works fine may be there is a bug with it:
It's useful when you have a similar event, Also you can pass different EventArgs, easiest way is to have a different Property which determines each form and add event in their set methods but bellow is general
public abstract class FormBase : Form
{
public virtual event EventHandler MyEventHandler;
}
public class Form3 : FormBase
{
public override event EventHandler MyEventHandler;
Form2 instance;
public Form3()
{
instance = Form2.Instance;
instance[this.GetType().ToString()] = this;
// or
//instance["Form3"] = this;
}
private void dataGridView1_CellEndEdit(object sender, EventArgs e)
{
// todo
if (MyEventHandler != null)
MyEventHandler(this, e);
}
}
public class Form2
{
Dictionary<string, FormBase> dic = new Dictionary<string,FormBase>();
public FormBase this[string index]
{
get
{
FormBase retVal = null;
if (dic.TryGetValue(index, out retVal))
return retVal;
return null;
}
set
{
FormBase retVal = null;
if (value == null)
return;
if (dic.TryGetValue(index, out retVal))
{
try
{
value.MyEventHandler -= MyEventHandler1;
}
catch
{
}
retVal = value;
retVal.MyEventHandler += MyEventHandler1;
return;
}
value.MyEventHandler += MyEventHandler1;
dic.Add(index, value);
}
}
private static Form2 instance;
public static Form2 Instance
{
get
{
if (instance == null)
{
instance = new Form2();
}
return instance;
}
}
private Form2()
{
}
private void MyEventHandler1(object sender, EventArgs e)
{
}
}
Change the access modifier to public instead of private.
Another option is to parse the eventhandler on Form1 to Form2:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataGridViewCellEventHandler dataGridViewCellEventHandler = new DataGridViewCellEventHandler(this.dataGridView1_CellEndEdit);
this.dataGridView1.CellEndEdit += dataGridViewCellEventHandler;
Form2 form2 = new Form2();
form2.CellEndEdit += dataGridViewCellEventHandler;
}
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
//Do something
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public event DataGridViewCellEventHandler CellEndEdit
{
add { dataGridViewOnForm2.CellEndEdit += value; }
remove { dataGridViewOnForm2.CellEndEdit -= value; }
}
}
This does however require that Form1 has access to Form2