I tryed to create new components from one base Windows Form, also I found difficulties when I worked with toolstrip components, for example :
how to bind a datagrid.datasource on a child form using events from a button (clicks) on the parent toolstrip?
I have to use some snippets on each child form for doing this, btw why?
// btnSearch
//
this.btnSearch.Click += new System.EventHandler(this.btnExec_Click);
private void btnExec_Click(object sender, EventArgs e)
{
//do stuff
}
Thanks
EDIT: I also know about modifiers issue :
I mean, I have to replace the toolstripbutton with a common button, also have to add more code on designer class (base form) :
grpCommonControls.Height = 20;
dtTScomponent = new ToolStripControlHost(grpCommonControls);
dtTScomponent.Alignment = ToolStripItemAlignment.Right;
toolStrip1.Items.Add(dtTScomponent);
tssbExporta.Alignment = ToolStripItemAlignment.Left;
toolStrip1.Items.Add(tssbExporta);
I was needed to add a simple toolstrip with some toolstrip controls on my base form, but the designer dont allow me to work correctly with those (I cannot route the events from toolstripbutton to my child forms as an example)
When you create a form that inherits another form that contains different controls, there are not event handlers automatically hooked up for you. Instead you need to do that as in your code sample. Another approach is to attach that event handler in your base form, and then have the base form expose events that you can listen to. Example:
In the base form:
public event EventHandler ExecInvoked;
private void btnExec_Click(object sender, EventArgs e)
{
OnExecInvoked(e);
}
protected virtual void OnExecInvoked(EventArgs e)
{
EventHandler evt = ExecInvoked;
if (evt != null)
{
evt(this, e);
}
}
Then, in your inherited form, you can either set up an event handler for the ExecInvoked event (you can probably do this using the events list in the property grid), or you can override the OnExecInvoked method:
protected override void OnExecInvoked(EventArgs e)
{
base.OnExecInvoked(e);
// do what the form should do when Exec is invoked
}
This way you have encapsulated the internals of the base form, so that the child form does not know what kind of control that raises the event (it could even be several different controls leading to the same event being raised), but the base form still provides a clear point where the child form can react on it.
To be able to change properties and subscribe to events of controls inherited from your parent Form (or UserControl), the parent form should set those controls' Modifiers property to protected (or, in general, to any value such that fields generated for controls in parent form are visible to the child form). The default value for Modifiers is private.
Related
I have many user control instances in my parent form. Now when I click a button in the parent form, I want all user controls change in a similar way. Instead of looping through my user controls and telling each control what to do, I want every control to listen to an event in the parent form and do the change once the event in the parent form is raised.
Like traffic lights: When they go to green, every car starts. I dont have to tell every single driver to start driving.
Would this be possible?
.Net implements an "Observer" pattern via events and delegates.
// this is a Pseudocode
form.button.Click += DoSomething; // (object, EventArgs)
DoSomething(...)
{
foreach(Control in form.controls)
{
// do whatever you need with your control
}
}
Now it is getting interesting. Lets say, you create custom buttons, textboxes; then you
public class CustomButton : Button.....
public class CustomTextBox : TextBox.....
// And in these ^^^ custom controls you can do this
override void ParentChanged(...)
{
var form = this.FindForm();
form.[SomeEvent] += Listen(.....); // (object, EventArgs)
base.ParentChanged(...);
}
public void Listen(.....) // (object, EventArgs)
{
// DO whatever you want with this control
// for each control type will be different code
}
This second approach lets .Net Observer to do all the work but you need to do inheritance.
The first approach seem easier. Only you need to cover all control types in some switch. In the second approach each control type can do what it needs to itself.
I'm trying to find a UserControl's ParentForm so I can hook some event handlers to it. I tried doing this in a ParentChanged event handler on the UserControl, eg:
ParentChanged += delegate(object sender, EventArgs args)
{
ParentForm.SomeEvent += ...
}
And this works fine if the UserControl's Parent happens to be the form. However, if the UserControl is embedded in a container control (in this case a SplitContainer), the UserControl gets added to the container control before the container control gets added to the top level form's controls (as controlled in the InitializeComponent method). That is, InitializeComponent() builds up the hierarchy from the leaves on up, so the leaves have no idea what form they'll eventually be placed on during construction.
So the ParentForm is null on the UserControl when the ParentChanged event is fired, and I don't get a ParentChanged event when the UserControl's parent's parent changes. I could add listeners for the parent's ParentChanged event, but I'd have to do so on up the entire control hierarchy which isn't particularly elegant.
I'd basically like to get notified of when the ParentForm changes for a UserControl. However there's no such event. I could hook in to things like the Load event, however this says it can get fired every time a control is shown if it's in a MDI container. That MSDN article suggests putting things in the constructor, but that's what I'm doing right now and it's not working out because of the timing for when things get initialized.
Any ideas?
I needed this too in my own customcontrol.
I subclassed a button and in the onclick I need to know the form.
So the trick is actually not getting the form in the load but getting it at the time you need it.
This worked for me :
private Form GetParentForm(Control parent)
{
Form Result = parent as Form;
if (Result == null)
{
if (parent != null)
{
// Recursive is cool
return GetParentForm(parent.Parent);
}
}
return Result;
}
I use it like this
protected override void OnClick(EvnetArgs e)
{
Form form = GetParentForm(Parent);
if (form != null)
{
// do stuff here
}
}
I have a custom control created, comprised of a bunch of text boxes, 1 button and radio buttons.
I then have a "parent" control which only has this 1 custom control placed on it, and in the code behind I have a reference to this control's Presenter.
The presenter handles the actual code for searching (when the one button is pressed). How do I set up the button click event on the child control to call the Search method from the presenter?
So I have the following:
CtlSearchDetails
ViewSearchScreen
PresenterSearchScreen
The button click event is on CtlSearchDetails and it needs to call the method on PresenterSearchScreen. I cannot figure out how to reveal this method to the instace of the control on ViewSearchScreen.
In your custom child control, you want to expose an event for the button click:
public event Action OnButtonClicked;
Then hook the button clicked event from the designer
private void btn_myButton_Clicked(object sender, EventArgs e)
{
if (OnButtonClicked != null)
OnButtonClicked();
}
Then in your parent container, you want to handle this event from the child control
this.myChildControl.OnButtonClicked += new Action(onChildButtonClicked);
private void onChildButtonClicked()
{
// Do your search here
}
The child controls of my custom control are obstruction the mouse events in my custom control. I have worked through the accepted answer and the answer at the bottom of this thread...
exposing-events-of-underlying-control
I haven't gotten them to work (the answer at the bottom seemed most straight forward to me). But really I would like to disable the events of them altogether. I have a pictureBox and a label, I don't need to interact with either of the child controls. Is there a way to disable them so they wont interfere with the events of my custom control?
Edit:
I'm using the custom control to gather and process a number of things and make them available as properties. When I click on it, I need to access to the properties. When the event happens at the child control, I don't have access to the propertied of my custom control. The following code is in my form...
public void Form1_MouseDown(object sender, MouseEventArgs e)
{
var myControl = sender as SubstanceViewer;
richTextBox1.Text = myControl.substanceInfo;
}
so I will need to access the properties of the parent control.
If you need the the events that are normally trapped by the child controls to be handled by the custom control itself, then simply wire up those events at run-time in the constructor of the custom control.
For example if you needed the MouseMove() event of the PictureBox and Label to fire the already wired up event of the UserControl:
public partial class SomeUserControl : UserControl
{
public SomeUserControl()
{
InitializeComponent();
this.pictureBox1.MouseMove += SomeUserControl_MouseMove;
this.label1.MouseMove += SomeUserControl_MouseMove;
}
private void SomeUserControl_MouseMove(object sender, MouseEventArgs e)
{
}
}
Be aware, though, that since different controls are firing the same handler you'll need to take that into account. For example, the e.X and e.Y values in the handler above would be relative to the source control.
*You can also wire these events up at design-time using the IDE itself, but I thought code better illustrated the solution.
I have tried a bunch of different things, so obviously I am now stuck... I have created a form, it has a button on it - that when clicked creates a new form. I can click away and create multiple forms this way. What I would like and can not get to work is to have the main form have a second button on it - that when clicked will change all of the background colors on the secondary forms.
Thanks - I am guessing I close, but then again - close doesn't work...
Bascally you do not need event or delegate type of things to solve this issue. In your secondary forms write a public method to change background color. Keep a list of secondary forms and when button is clicked just loop through all your secondary forms and call the color changing methods
Using events
In your parent form do something like this.
private event Action<Color> ChangeColor;
private void CreateAndShowForm()
{
var form2 = new Form2();
ChangeColor += form2.changeColor;
/*do other stuff to show form*/
}
private void button1_Click(object sender, EventArgs e)
{
ChangeColor(Color.Red);
}
In the child forms
public void changeColor(Color obj)
{
/*change background color*/
}
There are a few ways to achieve this, but one way is to keep a collection of all child Forms in the main form and call a custom change background color method on each of them. You can create a ChildFormBase class that they all can inherit from where you can define the method to avoid repeating it in all child forms.
You can also do this with an event that you raise in the MainForm that the child forms can subscribe to.
In .NET, when an event is raised, all the objects listening to it (registered as event listeners) are notified that the event has been raised and execute the respective event handler. Therefore, in your case, each subform should be registered to the specific event of the main form, as an event listener. Each time the main form raises the event, the subforms will be notified that the event has been raised and act accordingly.
You could see this as a guide to the events paradigm in C#.
Hope I helped!