I had created a simple C# program with Mainform.cs, Mainform.Designer.cs and Program.cs files with SharpDevelop.
In that, i added a label at Point(10,10) in the form like this:
l.Text="Welcome";
l.Location=new System.Drawing.Point(10,10);
l.Size=new System.Drawing.Size(100,100);
mainForm.Controls.Add(l);
And then added an event handler for identifying mouse clicking on the form. When clicking a label to change its text.
l.Text="Clicked";
But it only changes text when clicking point less than (10,10). How to make it to change text when clicking anywhere on the window?
Thanks!
Attach the same event handler also to label's Clicked event, not only the form's event. In the version you've described the click events are being consumed by the Label control, and not being passed to the form.
Of course attaching the same handler for both the Click event of your Form and your Label is OK, however what if you add more containers with nested relationship? I would go for a global Click event solution by using an IMessageFilter, something like this:
public partial class Form1 : Form, IMessageFilter {
public Form1(){
InitializeComponent();
Application.AddMessageFilter(this);
//Try this to see it in action
GlobalClick += (s,e) => {
l.Text = "Clicked";
};
}
public event EventHandler GlobalClick;
public bool PreFilterMessage(ref Message m){
if(m.Msg == 0x202){//WM_LBUTTONUP
EventHandler handler = GlobalClick;
if(handler != null) handler(this, EventArgs.Empty);
}
return false;
}
}
Related
I have a problem with User form Click that I am trying to make in C# using a usercontrol.
It consists of a picturebox and a label. I want to call the click event but the picturebox and the label don't do anything when I click them. Only the background area of the usercontrol does what I want it to do. Any ideas?
here's my code
for (int i = 0; i < listitems2.Length; i++)
{
listitems2[i] = new declined();
//adding sample data to each dynamic user
listitems2[i].dicon = dicon[i];
listitems2[i].did = did[i];
listitems2[i].dname = dname[i];
//adding data to flow layout panel
flowLayoutPanel2.Controls.Add(listitems2[i]);
// below line will assing this (usercontrolclick) event to every user control created dynamically
listitems2[i].Click += new System.EventHandler(this.UserControl_Click);
}
for click function
void UserControl_Click(object sender, EventArgs e)
{
string ctrlName = ((UserControl)sender).Name;
applicable obj = (applicable)sender;
studid.Text = obj.id;
studname.Text = obj.name;
pictureBox1.Image = obj.icon;
}
You added OnClick handler to your UserControl, so only clicks made on UserControl will be registered. To enable Click event for all the controls on your form, you need to add your click handler to all other controls.
But, according to your code, you're adding click handling on form where your control is located. In this case, you cannot register clicks on control from "outside" (you can by making Label and PictureBox controls public and adding handlers for their OnClick events but that is wrong way to do it)
My suggestion is to make custom event on your form and raise it on Form, Label and PictureBox click, and then make handler for that event on form which holds your UserControl.
Something like this:
//make custom eventHandler on your UserControl
[Browsable(true)]
public event EventHandler UserControlClicked;
//constructor
public UserControl1()
{
InitializeComponent();
//after intialize compoment add same handler for all three controls
this.Click += ControlClicked;
this.pictureBox1.Click += ControlClicked;
this.label1.Click += ControlClicked;
}
//this method will "catch" all clicks
private void ControlClicked(object sender, EventArgs e)
{
//raise event
UserControlClicked?.Invoke(this, e);
}
and on form where your custom control is, add handler for UserControlClicked (maybe with cast, I don't know what listItems2[i] contains):
listitems2[i].UserControlClicked+= new System.EventHandler(this.UserControl_Click);
or maybe like this (with casting)
(listitems2[i] as UserControl1).UserControlClicked+= new System.EventHandler(this.UserControl_Click);
and handle the rest in your UserControl_Click method like before
I have a user control named myControl. I have rendered another user control named dialog inside myControl as <uc:dialog x:Name="dialog"> .
I have a button named as myButton inside the dialog user control. I need to get the lostfocus event of myButton from the parent level .ie,myControl code behind.How can I get that? Which is the best way to do that?
var myButton= dialog.FindName("myButton") as Button;
if (myButton!= null)
{
myButton.LostFocus += myButton;
}
I tried like this. But it doesn't work.Why?
You could define such an Event in your UserControl.
Then just register for this event.
public event EventHandler ButtonLostFocusEvent;
private void Button_LostFocus(object sender, RoutedEventArgs e)
{
EventHandler testEvent = this.ButtonLostFocusEvent;
// Check for no subscribers
if (testEvent == null)
return;
testEvent(sender, e);
}
Refer to this previous question I asked where I couldn't get the click event for a UserControl on my form to fire off.
The way I have my control set up is I have the control itself sized to 50, 20. I then a have panel sized 25, 20 set to dock on the right side. In code within the UserControl itself, anytime the background of the control or the panel that acts as the "switch" are clicked, it fires off this code:
private void toggleClick(object sender, EventArgs e) {
if (toggleStatus) { // set to "on"
this.BackColor = Color.Red;
this.pnlSwitch.Dock = DockStyle.Left;
toggleStatus = false;
} else { // set to "off"
this.BackColor = Color.Green;
this.pnlSwitch.Dock = DockStyle.Right;
toggleStatus = true;
}
}
This works great and goes off every time. However, I put my UserControl in a form and tried to tie a click event to this method:
private void toggleSoundClick(object sender, EventArgs e) {
MessageBox.Show("Test");
}
When I click on the background of the control, this fires off and everything works like it should. However, if I click on the panel that acts as the "switch", the click event in my form doesn't fire (but the click event in the UserControl itself does, which isn't the issue). I can kind of understand this being something like z-indexing in CSS, but it still baffles me why a click event inside the control wouldn't cause it to fire off.
My question is, how can I get around this type of behavior?
edit I also can't integrate the behavior from the click event inside the form into the click event inside the UserControl. I have several of these controls on my form, and all have different behavior depending on which is clicked.
After taking Sinatr's suggestion I googled a bit more and found this post on here. What I ended up doing was unsubscribing all click events for the "switch" panel, then putting this code inside my UserControl.
public new event EventHandler Click {
add {
base.Click += value;
foreach (Control control in Controls) {
control.Click += value;
}
}
remove {
base.Click -= value;
foreach (Control control in Controls) {
control.Click -= value;
}
}
}
This made it so that when I subscribed the click event for the control itself to the toggleClick method, it also registered it with the "switch" panel (which is why I unregistered all other click events, otherwise it would fire off twice), and it also caused the toggleSoundClick method to be subscribed to the "switch" panel as well when I subscribed it to the control itself inside my form.
edit For my purposes I wanted to add the click events recursively to all controls, no matter the depth, so I changed the code to this
public new event EventHandler Click {
add {
subscribeToEvent(this, value);
}
remove {
unsubscribeFromEvent(this, value);
}
}
private void subscribeToEvent(Control control, EventHandler eventHandler) {
control.Click += eventHandler;
foreach (Control child in control.Controls) {
subscribeToEvent(child, eventHandler);
}
}
private void unsubscribeFromEvent(Control control, EventHandler eventHandler) {
control.Click -= eventHandler;
foreach (Control child in control.Controls) {
unsubscribeFromEvent(child, eventHandler);
}
}
In the UserControl code that is firing correctly, add
e.Handled = false;
By setting the EventArgs' Handled property to false, the click event is passed through and hopefully caught (again) by the listener in your form method.
I created a new Event in my user control (SearchControl) like this:
//Event which is triggered on double click or Enter
public event EditRecordEventHandler EditRecord;
public delegate void EditRecordEventHandler(object sender, EventArgs e);
//Supressing the events
private bool _raiseEvents = true;
private void OnEditRecord(System.EventArgs e)
{
if (_raiseEvents)
{
if (this.SearchResultGridView.FocusedRowHandle > -1)
{
if (EditRecord != null)
{
EditRecord(this, e);
}
}
}
}
Now this Event is called when user double click a row in a grid. So from the properties window I selected the MouseDoubleClick Event of the grid view and called the above created EditRecord event.
private void SearchResultListGridControl_MouseDoubleClick(object sender, MouseEventArgs e)
{
// Check whether the user clicked on a real and not a header row or group row
DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo info = SearchResultGridView.CalcHitInfo(e.Location);
if (info.InRow && !SearchResultGridView.IsGroupRow(info.RowHandle))
{
OnEditRecord(e);
}
}
Now the issue I am facing is every time I double click a row in grid view it calls the SearchResultListGridControl_MouseDoubleClick() which then calls OnEditRecord(), however the value of EditRecord is everytime null.
To solve this I checked the designer file of the Main Control which has SearchControl and could not find the EditRecord Event entry in this. So I manually created it like this:
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
Now the things are working fine, but my question is why it did not create it automatically at the first place? And as far I know it is not recommendable to add anything manually to the designer file..is there any other way I can do it?
Thanks
When you create event it has to be used in the form designer similar to how you are using MouseDoubleClick for the Grid (so you need to find event in the Misc category, because you didn't define CategoryAttribute, double clicked there, etc).
If I understand it right you want to subscribe to event automatically, when form is created. You can do this in the control constructor (find parent form control.Parent or control.FindForm()) or perhaps in the special method, which you have to call from the form constructor, which in turn is basically similar to wiring event manually (which you did in the designer created file, but, instead, you can do in the form file, which is totally ok to edit) Up to you.
Sure.
A better practice would be to add your binding line:
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
To the form's constructor. something like:
public MyForm()
{
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
//The rest of your constructor.
}
enter code hereI've built a winform MDI application based on two baseforms, a listform with a grid (_ListForm) and a dataform to display the child data (_DataForm).
When I load an inherited dataform into the MDI, the activated event from the base-form (_DataForm) is triggered and some properties are automatically set. When I load an inherited listform (_ListForm) into the MDI, the activated event is not triggered.
My childform doesn't have an (overrided) activated event, there is no significant difference in the two forms, just one triggers the event, one doesn't.
I've added the eventhandler in code and/or with the designer : no
trigger
I've added a new activated event in the childform and called
base.onActivated(e) : no trigger
For now I moved some of the code into the textchanged event (which also occurs once), but why is this Activated-event not being triggered?
Can add tons of code-samples if needed, but not sure what to post.
EDIT: Forgot to mention, it's the same with the LoadEvent - doesn't trigger in any way.
EDIT: Sources as per request:
_BaseForm : font and general background (no events)
public partial class _BaseForm : Form
{
public _BaseForm()
{
InitializeComponent();
}
_ListForm : grid and buttons
public partial class _ListForm : _BaseForm
{
public _ListForm()
{
InitializeComponent();
this.Activated += new EventHandler(_ListForm_Activated);
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.grid1.UltraGrid.DisplayLayout.Bands[0].Columns.ClearUnbound();
this.grid1.UltraGrid.DisplayLayout.Override.AllowAddNew = Infragistics.Win.UltraWinGrid.AllowAddNew.No;
this.grid1.UltraGrid.DisplayLayout.Override.AllowDelete = Infragistics.Win.DefaultableBoolean.False;
this.grid1.UltraGrid.DisplayLayout.Override.AllowUpdate = Infragistics.Win.DefaultableBoolean.False;
this.grid1.UltraGrid.DisplayLayout.Override.CellClickAction = Infragistics.Win.UltraWinGrid.CellClickAction.RowSelect;
this.grid1.PopulateGridColumns += new FB.Windows.Controls.Grid.PopulateGridColumnsEventHandler(grid1_PopulateGridColumns);
this.grid1.UltraGrid.InitializeLayout += new Infragistics.Win.UltraWinGrid.InitializeLayoutEventHandler(UltraGrid_InitializeLayout);
this.grid1.RowSelected += new FB.Windows.Controls.Grid.RowSelectedEventHandler(grid1_RowSelected);
}
_ListForm event (either in designer or code from ctor):
this.Activated += new System.EventHandler(this._ListForm_Activated);
this.Load += new System.EventHandler(this._ListForm_Load);
The event itself:
private void _ListForm_Activated(object sender, EventArgs e)
{
if (AutoSearchOnOpen)
{
button1_Click(sender, e);
this.grid1.Focus();
this.ActiveControl = this.grid1;
}
else
{
this.textBox1.Focus();
this.ActiveControl = this.textBox1;
}
}
I know the Click inside the activated event will fire each time it's activated, but for now that doesn't matter: the main problem is: the whole event wont fire. Although the event in the _DataForm (also inherited from _BaseForm) is fired.
In this case the grid (3rd party control) overloads (hijacks) the activated and loaded events for the form and don't trigger the base event after the original event.