I'm using the DockPanel Suite in my winforms app. The DockContent class is derived from System.Windows.Forms.Form class and my two forms, dockRounds and dockToolbox, inherit from the DockContent class.
This is the first time I've done this and this is probably a stupid question, but in runtime, how do I access the controls of the dockRounds and dockToolbox forms?
Here is how I load the two forms when the app first runs:
public partial class frmMainNew : Form
clsMWDockPanel mapPanel;
dockToolbox dockT = new dockToolbox();
dockRounds dockR = new dockRounds();
public frmMainNew()
{
InitializeComponent();
dockPanel = new DockPanel();
SuspendLayout();
dockPanel.Parent = panelMain;
dockPanel.Dock = DockStyle.Fill;
dockPanel.DefaultFloatWindowSize = new Size(108, 528);
dockPanel.BringToFront();
dockPanel.BackColor = Color.Transparent;
dockPanel.DocumentStyle = DocumentStyle.DockingSdi;
ResumeLayout();
string error = "Errors:\r\n";
try
{
loadRounds();
loadToolbox();
}
catch (Exception)
{
error = error + "The Toolbox and/or Rounds menu could not be created\r\n";
}
}
public void loadToolbox()
{
dockT.CloseButton = false;
dockT.ShowHint = DockState.Float;
dockT.Text = "Toolbox";
dockT.BackColor = Color.WhiteSmoke;
dockT.Icon = this.Icon;
dockT.Show(dockPanel);
}
public void loadRounds()
{
if (mapPanel == null)
{
CreateMapPanel().Show(dockPanel, DockState.Document);
}
mapMain.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
//mapMain.BringToFront();
dockR.CloseButton = false;
dockR.ShowHint = DockState.DockRightAutoHide;
dockR.Text = "Rounds Menu";
dockR.BackColor = Color.WhiteSmoke;
dockR.Icon = this.Icon;
dockR.Show(dockPanel);
}
DockContent CreateMapPanel()
{
mapPanel = new clsMWDockPanel();
mapPanel.ShowHint = DockState.Document;
mapPanel.Controls.Add(mapMain);
return mapPanel;
}
Many thanks in advance
leddy
There are several strategies you can use to achieve communication/linkage between objects on different Forms. Note : My reply here is not going to address any issues specifically related to DockPanelSuite, and is not going to consider the difference between the "secondary" forms being "independent" (i.e., they are not "owned" by the MainForm) or being made child Forms of the MainForm. This is a conscious choice made on the basis of believing that what you are asking about is independent of those possible variations in implementation.
the simplest strategy (if tedious for a lot of controls) is to declare Public Properties in your secondary Forms that expose the controls you want to manipulate from your Main Form. For example, let's say Form2 has a button, and you want to handle its click event on your main form :
In Form2 define a property like :
public Button form2Button
{
get { return button1; }
}
Now in the Load event of your Main Form, assuming that's where an instance of Form2 is created, you can subscribe to the Click event of the Button on Form2 :
Form2 myForm2;
Form3 myForm3;
private void Form1_Load(object sender, EventArgs e)
{
myForm2 = new Form2();
myForm2.form2Button.Click += new EventHandler(form2Button_Click);
myForm3 = new Form3();
}
And you can easily imagine that in Form3 you have a TextBox that you have exposed with a Public Property in the same way you exposed the Button on Form2.
So you can implement the MainForm's event handler like this for the Button click on Form2 :
public void form2Button_Click(object sender, EventArgs e)
{
// do something here with the TextBox on Form3
// myForm3.theTextBox.Text =
}
... other strategies ...
in your secondary form, for example, a button press can raise a Public Event which the Main Form (or any other entity to which Form2 is exposed) could subscribe to and then dispatch the appropriate whatever to the appropriate target.
you can abstract message-passing in general at a higher level into a single (perhaps static) class where publishers send messages, and the messages are dispatched to registered listeners.
Finally, the discussion here may be of interest to you :
Using The Controls Of One Form Into Another
best,
Your classes, dockRounds and dockToolbox should expose any properties/events that you want to access. So if you want to hook up to a control's event, route it to a public event.
You can set the access modifier on a control to make it as accessible as you like. The default is "Private" which is why you can't access the controls from the main form.
In Visual Studio, on the Properties tab, there is a Modifiers property which sets the access modifier that is used in the generated designer file.
Set this to "Public" and you be able to access the control from the main form.
I've just used this when I inherited one form from another. By setting the modifier to "Protected" (or "Protected Internal") I was able to access the controls defined in the base class.
Have you tried accessing the Controls property?
var controls = dockRounds.Controls;
Related
I have a Windows Forms App in C# with multiple UserControls.
In the UserControl1 I create panels dynamically, each panel containing multiple elements (checkbox, label listbox, picturebox, and multiple comboboxes). The values inside these elements differs between panels because I import the values from a Database. Also, I can add or remove elements from the listbox. Basically each panel is a presentation for a Pizza menu where you select the size (each size has its own price) and add or remove ingredients (from the listbox).
If you select one (or more) of the pizza's it is added in the UserControl2 (designated as a shopping cart). You can select multiple (different) pizza items from the UserControl1, and all of them will appear in the UserControl2 in the "shopping cart".
All these UserControls are contained in a panel in a Form and can be accessed by clicking a corresponding button.
My question is, how do I reload the UserControl1 from UserControl2?
Basically, after I'm done making an "order" (which can have multiple different items), I want to make a new "order" and I want the UserControl1 to look just like it was when I started the app.
I realize that I have to call the UserControl1_Load() method, but how do I do that from the UserControl2?
Or is there another method of "resetting" the UserControl1?
Obviously, I'm kind of new to C# so, please, have mercy on my soul.
Thank you very much in advance for your help!
I would implement an interface which each UserControl should implement to support this feature. The interface is a contract describing that the control has implemented a method. Just try to cast all usercontrols to that interface to support the restart functionality.
You should change it for your needs, but here is an example:
public interface ISupportInitialize
{
void Initialize();
}
public partial class MyUserControl : UserControl, ISupportInitialize
{
public MyUserControl()
{
// whatever you need to initialize
Initialize();
}
public void Initialize()
{
// remove old content if exists
// add new content
}
}
And in your main window:
public void ReInitializeControls()
{
// assume that panel1 contains the controls.
var userControlsWithInitialize = panel1.Controls.OfType<ISupportInitialize>();
foreach(var control in userControlsWithInitialize)
control.Initialize();
}
Calling the Load() method may not be sufficient. If you want a total reset behavior, you can remove the current control and add a brand new one in place of it.
Assuming you know how to implement an event handler, this goes inside the user control which triggers the reset operation, as a member variable:
public EventHandler OnOrderCompleted;
And when the order is completed, the control should invoke:
private void button1_Click(object sender, EventArgs e)
{
if (OnOrderCompleted != null)
{
OnOrderCompleted.Invoke(this, new EventArgs());
}
}
To keep coupling at minimum, this control should not directly know about the user control to be reset, but should inform any observers about the completion of an order. In our case, this can be the form hosting all the controls: (We name the triggering control orderControl here)
public Form2()
{
InitializeComponent();
orderControl.OnOrderCompleted += OnOrderCompleted;
}
private void OnOrderCompleted(object sender, EventArgs e)
{
Point currentLocation = productsControl.Location;
Controls.Remove(productsControl);
productsControl = new UserControl1();
productsControl.Location = currentLocation;
Controls.Add(productsControl);
}
Hope this helps.
I am having a problem controlling a textbox. I need to change a value from outside of Form1.cs where the textbox is located for this I have found this snippet.
public void UpdateText(string newValue)
{
torrent_name0.Text = newValue;
}
this allows me in theory to control the textbox outside of Form1.cs, but here comes the problem, every time I want to access it I create a new instance of Form1 instead of using the old one and refreshing it.
Form1 frm = new Form1();
frm.UpdateText("aaaaaaaaaaaa");
frm.Show();
am I missing something? is there a better way to do this? I have tried multiple ways to update the new form but got nowhere.
Bokker,
You will have to have a reference to the singular form1 to which all things refer.
If this is a child form, then as Aybe commented, create a public member of your mainform and name it something.
Public Form myForm1;
You probably have some Event by which you would like Form1 be launched...
A Button click, menu item, toolbar item, etc. In that event you will have to check if the form exists and create if required.
private SomeEvent() {
if (myForm1 == null)
{
myForm1 = new Form1();
myForm1.Show(this);
}
myForm1.UpdateText("some text");
}
Alternatively, you could create the form in the Form Load event, just so long as you create the form prior to attempting the myForm1.UpdateText()
If you follow this paradigm, you are creating myForm1 as part of the main form, best practice says you should also dispose of the form in your main form Closing Event.
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (myForm1 != null)
{
myForm1.Close();
myForm1.Dispose();
}
}
This is all off the top of my head, so it might not be perfect.
In that case you can pass the instance of form in the method as argument and make the changes like
public void UpdateText(string newValue, Form1 frm)
{
frm.torrent_name0.Text = newValue;
}
I have a button and hidden textbox on my main form. When I press the button it will hide the main form and show the second form. When I press the button on the second form I want to show the main form again but this time I need to show the hidden textbox. I know how to pass the text from a textbox to another form but not just the reference of the textbox.
You better pass the complete main form instance for the second form, and create a public function to set the textbox to visible, or create a property around it.
Something like:
//form1
Form2 second = new Form2(this);
}....
public void ShowTextBox()
{
textbox1.Visible=true;
}
//form2
Form parent;
public Form2(Form _parent)
{
parent=_parent;
}
///later
parent.Show();
parent.ShowTextBox();
Sounds to me like a custom event would be a better approach. Have the secondary form expose an event, which is raised at whatever appropriate time (your button press). In your main form, when you create your instance of your second form, subscribe to that event. Then run your "unhide" code from within the mainform's event subscription.
This keeps the coupling down on the two forms and results in much more easily maintainable and extensible code (for best effect, use interfaces, but events are a good middle ground for learning).
Something like this:
(it's been a long time since I worked with winforms, or events even, so if this needs refining let me know)
// your secondary/popup form's class
public partial class Form2 : Form
{
// add a custom event
public EventHandler<EventArgs> MyCustomEvent;
// link up your button click event
void InitializeComponent() {
myButton.Click += myButtonClick;
}
// when your button is clicked, raise your custom event
void myButtonClick(object sender, EventArgs, e) {
onMyCustomEvent();
}
// this "broadcasts" the event
void onMyCustomEvent() {
EventHandler<EventArgs> h = MyCustomEvent;
if (h != null) {
h(this, new EventArgs());
}
}
}
// your main form's class
public partial class MainForm
{
void InitializeComponent() {
// ...
}
void showForm2() {
var form2 = new Form2();
form2.MyCustomEvent += form2CustomEvent;
form2.Show();
}
void form2CustomEvent(object sender, EventArgs e) {
myHiddenTextBox.Visible = true;
}
}
All in all this is a much better approach in terms of code architecture. Now the popup doesn't care who opens it (it has no reference to the main form), and the custom event (which is really what you're after) can be managed to any level of control you need, without interfering how other thing work (for example, perhaps later you may want to have a different action that fires this same custom event...)
Food for thought.
At first i disable a Toolstrip menu item so that when a user click the "Enable" button, the Toolstrip menu item can be enablem like:
private System.Windows.Forms.ToolStripMenuItem QLKHTSM;
The QLKHTSM is disable on the forms.
The problem is the Enable button is on the other form, so i tried to interact between 2 forms by this code(under the same form of that ToolStripMenuItem)
public static void enabletoolstrip()
{
QLKHTSM.enable = true;
}
but the problem is with static, the QLKHTSM is unavailable, and without static, i can't call it in the other form.
Please help. Thanks.
In the form where QLKTHSM is, Go to be Properties of QLKTHSM and change the Modifier property to Public. Then go to the second form and use.
public void enabletoolstrip()
{
FirstForm f1 = (FirstForm)Application.OpenForms["FirstForm"];
f1.QLKHTSM.Enabled = true;
}
If the form with QLKHTSM is not yet shown then you can create a global object.
FirstForm f1 = new FirstForm();
Then in your enable tool strip
public void enabletoolstrip()
{
f1.QLKHTSM.Enabled = true;
}
Then wherever you want to show the form you use
f1.Show();
I have two forms in a windows form application. lets call them "first form" and "second form".
i want by clikcing on a button on second form, change the property of one of the controls of the first form. i've defined an event for this. by that i mean when i click on the second form's button, a method within the first form is called. here's the method:
// changes the visibility of the specified control
public void change_visibility()
{
this.new_customer_label.Visible = true;
}
but when i set a breakpoint on this method and check the value after it is executed. the property has't changed. what is wrong? thanks in advance
note: on the second form button's click event, i also close the form.
So firstly, Open up Form1.designer.cs and change the control to public
Form1 this will open Form 2.
Form2 frm2 = new Form2();
frm2.Owner = this;
frm2.Show();
Form2 this will change the property of a control in Form 1
(this.Owner as Form1).label1.Visible = true;
Here is an example of what you can do:
class Form1 : Form {
private Label labelInForm1;
public string LabelText {
get { return labelInForm1.Text; }
set { labelInForm1.Text = value; }
}
}
class Form2 : Form {
Form1 form1; // Set by the property
private Form1 Form1 {
get { return form1; }
set { form1 = value; }
}
private ChangeVisibility()
{
Form1.labelInForm1.Visible = true;
}
}
"note: on the second form button's click event, i also close the form."
Then it would probably be a better design to display the second form with ShowDialog() instead of Show(). Something like:
Form2 f2 = new Form2();
f2.ShowDialog(); // code STOPS here until "f2" is closed
this.new_customer_label.Visible = true;
By default, the designer generates code in the 'Form1.Designer.cs' class. In there, you can see that all the controls are set private, change them to public and then try again...
As you will search this problem on internet you will find different solutions but I think the best solution is to make controls public then you can access these controls from any form.
Follow these instructions.
Open your desire form whose control properties you want to access
Open Form.Designer.cs
Change the desire control class to public
Go to the main form where you want to access or change property
Write this code
Form Form2 objForm=new Form2();
Now access your control property here
objForm.new_customer_label.Visible=true;
I hope this will be helpful to you!!!