I have a User Control for typical CRUD like actions on my WinForm app.
Validate, Insert, Update, Clear, Cancel, and Delete.
On every form I put this on I end up adding the click event, ucPersonNav.btnValidate.Click += new EventHandler(btnValidate_Click);, for every button.
What I am wondering is can I have the Events be on the User Control themselves and just have them point to a Method that I override on a Form by Form basis?
Something like this -->
namespace psUserControls
{
using System;
using DevExpress.XtraEditors;
public partial class ucVIUCCDwithWhoDoneIt : XtraUserControl
{
public ucVIUCCDwithWhoDoneIt()
{
InitializeComponent();
}
private void btnValidate_Click(object sender, EventArgs e)
{
ValidateEvent();
}
}
}
And then on a Form have this -->
void ValidateEvent()
{
if (dxValidDiagnosis.Validate())
{
if (planDiagnosisID != 0)
{
ucNavDiagnosis.btnUpdate.Enabled = true;
ucNavDiagnosis.btnDelete.Enabled = true;
}
ucNavDiagnosis.btnInsert.Enabled = true;
}
}
Is this feasible? Is it idiotic? If Yes then No then what steps do I need to take to make this work?
Thanks
i think .. not a bad idea..
but the approach would be very specific to your application.
we can have an enum for CRUD buttons - 6 enum items as you specified.
We can have a single event handler - delegate which takes above enum as a parameter.
Write an event (MyButtonClickedEvent) for this delegate which will be fired on each button clicked event.
on your control, on each button clicked event you can fire this event with respective enum item as a parameter.
e.g. on Validate button click, fire MyButtonClickedEvent with parameter as validate enum item.
On Inser button click, fire same MyButtonClickedEvent with parameter as Insert enum item.
This way you will have to handle single event on your form. You will be firing different events from your control. But this is to be done only once. On your form you will write a just one single handler - Method. In this method, you can differentiate depending on the enum type. .Net supports enum in switch-case construct. So you can easily identify the opteration that you have to perform.
All the users of your control will find it easier as they have to handle just one event. They will ignore the cases in switch construct which they are not interested.
Hope this helps.
You just need to define ValidateEvent as an event. In your UserControl:
public event EventHandler ValidateEvent;
On the form:
ucNavDiagnosis.ValidateEvent += new EventHandler(<name of event handler function>);
It's probably not a great idea to be accessing the buttons of the UserControl directly, however.
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.
There is Activated event in a Window in WPF. What is the the closest match for Activated event for a page. I want to use an event that triggers every time a page is displayed.
How about using the IsVisibleChanged event.
In your window, either your base class definition that you use throughout your app, or just the one you are interested in. Add a call at the opening of it something like
public class MyBaseclassWindow : Window
{
public MyBaseclassWindow()
{
IsVisibleChanged += MyBaseclassWindow_IsVisibleChanged;
}
private void MyBaseclassWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// e.NewValue will be TRUE when the visibility is coming back on
if ( !e.NewValue )
return;
// do whatever you want every time window becomes visible.
}
}
If this is something you want done throughout your system, then you can just use THIS window as your base window by always using it as forms are created.
There is the Loaded event which occurs when the element (Page) is laid out, rendered, and ready for interaction.
The Frame class, which I guess is used to host your pages, also has a ContentRendered event that you can handle.
I have a very simple requirement, i.e. I want to send a synthetic event to a UIElement, in this case, a Grid. What I want is simply that I be able to send a synthetic event to an UIElement.
For example,
StackPanel myPanel;
StackPanel topPanel;
topPanel.MouseLeftButtonUp += new MouseButtonEventHandler(topPanel_MouseLeftButtonUp);
private void topPanel_MouseLeftButtonUp(object sender, MouseEventArgs args) {
// Here I want to send the MouseLeftButtonUp event to myPanel
}
It is possible using RaiseEvent, but it is a protected event and hence I cannot just call it on an instance of any UIElement. So how do I go about sending a synthetic event on existing classes?
P.S: The reason that I cannot create custom inherited classes is that the current code base is too huge and the number of changes that will be required in case I take such an approach are not feasible.
Any help is greatly appreciated.
Regards,
roahn
Instead of raising events, you could just move the relevant code from the event handler to a method. Then, you can just call the method whenever you want to simulate a button click. However, if you want to simulate the button click on an element, you could do this:
//Assuming myPanel_MouseLeftButtonUp is the event handler for myPanel
myPanel_MouseLeftButtonUp(null, null);
I have a Windows Forms Application. I have several forms in this application (a main form, and several specialized forms), and on only one form, click events are not firing for any of my buttons.
It is not that the code in the handler is broken. This can be determined by the fact that a breakpoint on the first line of the handler is never reached when clicking the button.
Other events are working (I'm using CheckedChanged events on this form and they are behaving).
My team members have reviewed, and also can't spot the problem.
Here is a simplified view of my code:
Designer Generated Code
partial class MyForm
{
private System.Windows.Forms.Button addButton;
private void InitalizeComponent()
{
this.addButton = new System.Windows.Forms.Button();
this.addButton.Name = "addButton";
// Drawing statements here
this.addButton.Click += new System.EventHandler(this.addButton_Click);
this.Controls.Add(this.addButton);
}
}
My Code
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
}
private void addButton_Click(object sender, EventArgs e)
{
MessageBox.Show("The debugger is not reaching a break point on this line");
}
}
Edit: Additional Information from Testing
There are several data-bound dropdownlists in my form. I have discovered that the click event only fails to fire if I make a selection in a drop down box first.
If I make no selections, the break point in the button's handler fires. Otherwise it doesn't. There are no events registered on these drop down lists.
Here is the reason:
When using data binding, when you enter a value in a data bound control, it first tries to validate entry and then if the entry was valid, data binding will put the value in data source, but if a validation error occurs validation returns false and your control goes to invalid mode.
When a child control of form didn't validate, by default you can not change focus from invalid control.
Click on a button by default causes validation of the control that are losing the focus, so you can't click on button, as you see your button reflect to mouse but not actually click.
The same problem will happen if you handle Validating event of a control like TextBox and set e.cancel = true.
Here is the fix:
you can fix this behavior using either of following options:
Set CausesValidation property of your button to false
Set AutoValidate property of your form to AutoValidate.EnableAllowFocusChange
This will do the trick for you
Change
public ScheduleMeeting()
{
InitializeComponent();
}
to
public MyForm()
{
InitializeComponent();
}
I have discovered the issue after further testing.
I the issue is not with button events, but with the form becoming blocked after making a selection from a drop down box.
I have not yet discovered why the form blocks after the drop down is selected (it has no events, but does have databinding, so there are some possible causes there).
Thank you for all your help!
I have a windows forms app where I have split different functionality into several user controls. I want each of these user controls to have an accept button.
Any best practices here?
My idèa is to detect which user control that has focus, and than set it in the parent Form.
Any other idèas?
The best practice is usually to only have one accept button for your form so that its behavior is consistent. It generally would be confusing for users if hitting return caused different actions depending on which section of the form had focus. However, if you have a specialized application or users have requested this feature then I think the solution you propose would work.
Jan Miksovsky has an excellent blog on UI design, and wrote an article about this very thing.
Most UI platforms allow a designer to
indicate which button in a dialog
should be the default button: the
button that will be pressed if the
user types the Enter key. The default
button is generally the button the
user is most likely to press next,
often a button like OK that closes the
dialog. In very high-traffic dialogs,
you may want to consider dynamically
changing the default button to save
keystrokes and help speed the user's
task.
The example he uses is the "Select Names" dialog in Microsoft Outlook, which changes the default button depending on what you are doing.
I assume each user button is its own instance on the individual user controls?
If so then you can trap the button events on the Parent form. If you expose the individual buttons through a property you can tie into their Click events. Like all controls they have a name property so you can have one method that is called on all button click events.
Below I have a partial sample code. I have two user controls that have one button each. The button on UC1 is named "btn1" and "btn2" for UC2. I call the exposed property "ButtonOK"
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public Button ButtonOK
{
get { return btn1; }
}
}
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
}
public Button ButtonOK
{
get { return btn2; }
}
}
Now on the parent ("Form1") when it loads have a mthod that ties into the Click events of each button but it calls the same method. Inside the method I test for the "Name" property.
public Form1()
{
InitializeComponent();
}
void Form1_Load(object sender, EventArgs e)
{
RegisterButtonEvents();
}
void RegisterButtonEvents()
{
userControl11.ButtonOK.Click += new EventHandler(ButtonOK_Click);
userControl21.ButtonOK.Click += new EventHandler(ButtonOK_Click);
}
void ButtonOK_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
if (btn != null)
{
if (btn.Name == "btn1")
{
Console.WriteLine(" ButtonOK from UserControl1 was pushed. The tag is " + btn.Tag.ToString());
}
else if (btn.Name == "btn2")
{
Console.WriteLine(" ButtonOK from UserControl2 was pushed. The tag is " + btn.Tag.ToString());
}
}
}
You can also user the "Tag" property of a control. This property can be very useful as it can reference objects.
You don't need to do exactly as shown but you can use any "Parent" form to get a reference to the UserControls, have them expose their Buttons, then you can do anything you want with properties and events from those Buttons (or any control for that matter).
Keep in mind that if you are tying into the click event on the user control also (in addition to the parent form), you will have to be mindful of the order in which it will enumerate through it list of delegates and execute code after the event is intiated.
Hope that helps.
I know this is an old post, but I think I figured it out.
Use the "Enter" event on each user control from the main form, such that when the user "enters" (focuses on) the user control, this.AcceptButton = myUserControlButton. You can also use the "Leave" event on each user control to set the accept button back to the default, if you have one.
I'm not sure if I understood your question correctly.
If you want to assign one event to several buttons:
For this you could for instance:
- Get the button name on the Button_Click event.
- Enumerate between names
- Iterate over the controls.
Example bellow:
"How to get the button name from the Button_Click event".
// First; dont forget to assign the "Button_Click" event to your Button(s).
private void Button_Click(object sender, EventArgs e)
{
// The line bellow assigns to "btn" variable the currently clicked button.
Button btn = (Button)sender;
// Then using a switch block; you can compare the button name and
// perform the action desired for the clicked button.
switch(btn.Name)
{
case "buttonName1": /* Do Something Here */ break;
case "buttonName2": /* Do Something Here */ break;
// etc
}
}
Additionally; if you require; there's always the way to retrieve the Button outside the form class by exposing them.