Programmatically click on a CheckBox - c#

Is there a way to programmatically generate a click event on a CheckBox? I am looking for an equivalent to Button.PerformClick();

Why do you need to simulate a click, doesn't this line of code fits your need?
myCheckBox.Checked = !myCheckBox.Checked;
If you need to execute logic when the state of the CheckBox changes, you should use CheckedChanged event instead of Click.
private void CheckBox1_CheckedChanged(Object sender, EventArgs e)
{
MessageBox.Show("You are in the CheckBox.CheckedChanged event.");
}

Those solutions above calls Checkbox.CheckedChanged event.
If you want to explicitly call Click event you can this:
checkBox1_Click(checkBox1, null);

Why do you want to generate a click event on the CheckBox?
If you want to toggle it's value:
theCheckBox.Checked = !theCheckBox.Checked;
If you want to trigger some functionality that is connected to the Click event, it's a better idea to move the code out from the Click event handler into a separate method that can be called from anywhere:
private void theCheckBox_Click(object sender, EventArgs e)
{
HandleCheckBoxClick((CheckBox)sender);
}
private void HandleCheckBoxClick(CheckBox sender)
{
// do what is needed here
}
When you design your code like that, you can easily invoke the functionality from anywhere:
HandleCheckBoxClick(theCheckBox);
The same approach can (and perhaps should) be used for most control event handlers; move as much code as possible out from event handlers and into methods that are more reusable.

I'm still setting up a new workstation so I can't research this properly at the moment, but with UI Automation maybe it's possible that the checkbox supports the IInvokeProvider and you can use the Invoke method?

I don't think you can generate a click event in that way without calling the checkBox_Click event handler directly. But you can do this:
checkBox.Checked = !checkBox.Checked;
The CheckedChanged handler will still be called even if you do this.

The Button PerformClick() method validates the active control, testing whether the active control can lose the current focus. There are two ways to possibly do the same thing for a CheckBox. Approach #1 is to use reflection to call the methods that are internal to the Control class:
public class CheckBoxPerformClick : CheckBox {
private readonly static MethodInfo callValidateActiveControl;
private readonly static PropertyInfo propValidationCancelled;
static CheckBoxPerformClick() {
try {
Type ty = typeof(Control);
Type outBool = Type.GetType("System.Boolean&");
callValidateActiveControl = ty.GetMethod("ValidateActiveControl", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { outBool }, null);
propValidationCancelled = ty.GetProperty("ValidationCancelled", BindingFlags.Instance | BindingFlags.NonPublic);
} catch {}
}
public CheckBoxPerformClick() : base() {
this.Text = "Checkbox";
this.Appearance = Appearance.Button;
}
public void PerformClick() {
if (callValidateActiveControl != null && propValidationCancelled != null) {
try {
Object[] args = new Object[1];
bool validate = (bool) callValidateActiveControl.Invoke(this, args);
bool validatedControlAllowsFocusChange = (bool) args[0];
if (validate || validatedControlAllowsFocusChange) {
bool cancelled = (bool) propValidationCancelled.GetValue(this);
if (!cancelled) {
ResetFlagsandPaint();
OnClick(EventArgs.Empty);
}
}
} catch {
}
}
}
}
Approach #2 tries to do the same thing, but without reflection:
public class CheckBoxPerformClick2 : CheckBox {
public CheckBoxPerformClick2() : base() {
this.Text = "Checkbox";
this.Appearance = Appearance.Button;
}
public void PerformClick() {
bool validate = CanPerformClick();
if (validate) {
ResetFlagsandPaint();
OnClick(EventArgs.Empty);
}
}
// before allowing a click, make sure this control can receive the focus, and that other controls don't require validation
public bool CanPerformClick() {
if (!CanSelect)
return false;
Control c = this.Parent;
while (c != null) {
if (c is ContainerControl)
break;
c = c.Parent;
}
bool valid = true;
if (c is ContainerControl) {
var cc = (ContainerControl) c;
valid = cc.Validate(true);
}
return valid;
}
}

Related

How to enable a button to when one of my textbox changed in C#?

Today I got a problem in my development.
I have a Windows Form like this :
I need to enable the button "Appliquer" when the content of one of my textbox change.
I know that I can put the KeyPress event on each textbox and enable my button with that. In this window it can be easy to do that because there is only 10 textbox but I have an other window with more of 100 textbox and I think there is a better solution.
I tried to put the Keydown event directly in my windows form but it doesn't work.
So my question is, how can I do this. If someone have an idea ?
Thank you in advance !
Thomas
Since you already have 100+ textboxes in your form. I am assuming performance is not an issue for you.
In your form constructor, call this method. It will attach the event to all the textbox controls present in your form & inside sub controls such as groupbox, panel etc. (if you require)
There could be better ways of iteration..
public Form1()//your constructor
{
InitializeComponent();
AttachEvent(this);
}
void AttachEvent(Control CTrl)
{
foreach (Control c in CTrl.Controls)
{
if (c is TextBox)
{
c.TextChanged += new EventHandler(c_TextChanged);
continue;
}
if (c.HasChildren)
{
AttachEvent(c);
}
}
}
void c_TextChanged(object sender, EventArgs e)
{
//Your Code here btnGo.Enabled = !btnGo.Enabled;
}
What you can do is to extend TextBox make a field ( accessible from the designer ) to bind that TextBox into some other control.
public class MeTextBox
: TextBox
{
public override string Text
{
get { return base.Text; }
set
{
if ( m_DependantControl != null )
{
m_DependantControl.Enabled = !string.IsNullOrWhiteSpace(value);
}
base.Text = value;
}
}
Control m_DependantControl;
[Browsable(true)]
public Control DependantControl
{
get { return m_DependantControl; }
set { m_DependantControl = value; }
}
}
Now you can use MeTextBox as a regular TextBox. And if you want to make it control Enabled flag of some other Control you can just specify DependantControl property which will be accessible in the designer.
Fitting this into your example (code):
// assume you have a Button named btnConfirm
// and want to enable this button only when your `TextBox` has some text
MeTextBox mtb = new MeTextBox();
mtb.DependantControl = btnConfirm;
And if you do not want to make it in the code you can use designer directly.
To make it other way around ( one button dependant on many text boxes ) you can extend Button object :
public class MeButton
: Button
{
List<TextBox> m_DependantOn = new List<Control>();
[Browsable(true)]
public List<TextBox> DependantOn
{
get { return m_DependantOn; }
set { RemoveEvents(); m_DependantOn = value; AssignEvents(); }
}
void RemoveEvents()
{
foreach(TextBox ctrl in m_DependantOn)
ctrl.TextChanged -= WhenTextChanged;
}
void AssignEvents()
{
foreach(TextBox.ctrl in m_DependantOn)
ctrl.TextChanged += WhenTextChanged;
}
void WhenTextChanged(object sender, TextChangedEventArgs e)
{
this.Enabled = true;
}
}

Need a better way to Iterate through Form Controls

In my WinForms application written in C# there is a Button on one Form which needs to slightly alter the appearance of a second Form (just change the Text on a Button).
I have managed to do this, but the code is horribly long, and I believe there must be a much more concise way of achieving the same thing.
Here is my code for the Button on Form frmConflicts and how it changes the Text on the Button btnAddCase on Form frmAdmin (works, but seems too long) -
private void btnNoConflicts_Click(object sender, EventArgs e)
{
try
{
foreach (Form f in Application.OpenForms)
{
if (f.Name == "frmAdmin")
{
frmAdmin a = (frmAdmin)f;
a.conflictsClear = true;
foreach (Control ctrl in a.Controls)
{
if (ctrl.Name == "panAdmin")
{
foreach (Control ctrl2 in ctrl.Controls)
{
if (ctrl2.Name == "tabControlAdmin")
{
TabControl tab = (TabControl)ctrl2;
foreach(TabPage page in tab.TabPages)
{
if (page.Name == "pageNewCase")
{
foreach (Control ctrl3 in page.Controls)
{
if (ctrl3.Name == "panCaseDetails")
{
foreach (Control ctrl4 in ctrl3.Controls)
{
if (ctrl4.Name == "btnAddCase")
{
ctrl4.Text = "Add Case";
}
}
}
}
}
}
}
}
}
}
}
}
this.Close();
}
catch (Exception eX)
{
MessageBox.Show("frmConflicts: btnNoConflicts()" + Environment.NewLine + eX.Message);
}
Any help to significantly reduce the amount of code would be much appreciated, as I am going to need to do similar interactions between Forms elsewhere in my application.
If your button is added through designer and is not dynamically created the solution is simple: add a method inside your frmAdmin like
public void ChangeCaption(string caption)
{
btnAddCase.Text = "Add case";
}
and then
var frmAdmin = Application.OpenForms.OfType<Form>().FirstOrDefault(x => x.GetType() == typeof(frmAdmin));
if (frmAdmin != null)
{
frmAdmin.ChangeCaption("Add case");
}
I think it`s help to you
foreach (Form f in Application.OpenForms)
{
var controls =this.Controls.Find("btnAddCase", true);
if(controls!=null)
foreach(var control in controls)
{
control.Text="Add case";
}
}
If the the appearance of second from require a change on first from you should solve this in another way.
The best is that your button that require a change should be open for capture the event of form two open and then apply required change.
In the place where you declare your button you should assign to it a listener that will capture the Form2 opening and then apply action.
so in the method private void btnNoConflicts_Click(object sender, EventArgs e) you should trigger event for that button to capture instead off searching it.
You could use LINQ + ControlCollection.Find:
Control btnAddCase = Application.OpenForms.Cast<Form>()
.Where(f => f.Name == "frmAdmin")
.SelectMany(f => f.Controls.Find("btnAddCase", true)) // true means recursive
.FirstOrDefault();
if(btnAddCase != null)
btnAddCase.Text = "Add Case";
You could create a public property and subscribe to a PropertyChanged event from your form, you'll need your class that has the public variable to extend INotifyPropertyChanged.
//Your class
public class ButtonText : INotifyPropertyChanged
{
private string _buttonText;
public string ButtonValue
{
get{ return _buttonText; }
set
{
//Sets the value of _buttonText to the value passed in an argument
_buttonText = value;
RaisePropertyChanged("ButtonValue");
}
}
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
In your form class you'd bind to the property ButtonValue property of the ButtonText class like so:
ButtonText buttonObj = new ButtonText();
//Property field to bind, object to bind, property to bind
btnAddCase.DataBindings.Add("Text", buttonObj,"ButtonValue");
buttonObj.ButtonText = "Your text to bind.";
Because the btnAddCase.Text property is bound to the ButtonValue property of the ButtonText class, your btnAddCase.Text property will reflect the value of your ButtonText.ButtonValue property at all times, it's also a two way binding.

How to remove and re-attatch EventHandler to controls in c#?

I've read this answer.
It just tell me how to remove the click event from a button control. I want to know how to change the code (especially the GetField("EventClick"... part!) so I can do the same thing with other controls. For example, I want to remove the TextChanged event of a TextBox.
And I also want to know how to re-attach the event handler.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.Length < 10) return;
MessageBox.Show("do something");
}
private void Form1_Load(object sender, EventArgs e)
{
Tools.mkTextBoxWithPlaceholder(textBox1, "hi, input here...");
}
}
class Tools
{
public static void mkTextBoxWithPlaceholder(TextBox tb, string placeholder)
{
tb.Tag = placeholder;
tb.GotFocus += new EventHandler(tb_GotFocus);
tb.LostFocus += new EventHandler(tb_LostFocus);
}
private static void tb_GotFocus(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
tb.Clear();
}
private static void tb_LostFocus(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
//TODO Remove the TextChanged event handler here.
tb.Text = tb.Tag as string;
//TODO Reattach the TextChanged event handler here.
}
}
With the code above, the textBox1 will have a function like placeholder.Maybe you can just give me some help on how to add the placeholder to a textbox. That's what I want.
Remove
Mybutton.event -= methodname;
Reattach
Mybutton.event += methodname;
Here is a solution to your problem, according to this post of mine.
These helper methods let you manipulate any event for a specific control:
// Also searches up the inheritance hierarchy
private static FieldInfo GetStaticNonPublicFieldInfo(Type type, string name)
{
FieldInfo fi;
do
{
fi = type.GetField(name, BindingFlags.Static | BindingFlags.NonPublic);
type = type.BaseType;
} while (fi == null && type != null);
return fi;
}
private static object GetControlEventKey(Control c, string eventName)
{
Type type = c.GetType();
FieldInfo eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName);
if (eventKeyField == null)
{
if (eventName.EndsWith("Changed"))
eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName.Remove(eventName.Length - 7)); // remove "Changed"
else
eventKeyField = GetStaticNonPublicFieldInfo(type, "EVENT_" + eventName.ToUpper());
if (eventKeyField == null)
{
// Not all events in the WinForms controls use this pattern.
// Other methods can be used to search for the event handlers if required.
return null;
}
}
return eventKeyField.GetValue(c);
}
private static EventHandlerList GetControlEventHandlerList(Control c)
{
Type type = c.GetType();
PropertyInfo pi = type.GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
return (EventHandlerList)pi.GetValue(c, null);
}
and then you can use them to temporarily detach an event handler:
private static void tb_LostFocus(object sender, EventArgs e)
{
TextBox tb = (TextBox)sender;
var eventList = GetControlEventHandlerList(tb);
var eventKey = GetControlEventKey(tb, "TextChanged");
// Remove the handlers
var handlers = eventList[eventKey];
eventList.RemoveHandler(eventKey, handlers);
// ... perform your task
// Reattach the handlers
eventList.AddHandler(eventKey, handlers);
}
If you want to know what is really happening here, read on.
Windows Forms uses the EventHandlerList class to maintain control events. Every event is accessed using a simple key of type object. Keys are stored in private fields of the control. The only way to access this data is using reflection, but we should know the name of the event key field. By decompiling the the Control class and it's descendants, we can see that the keys use different names. I extracted three common naming pattern among the keys, and used them in the GetControlEventKey method.
This is the mechanism that WinForms controls use to hold the event handlers. There is no special thing about it. It is just a design choice.

Differentiating between events raised by user interaction and my own code

The SelectedIndexChanged event gets fired in my application from a combo box when:
the user chooses a different
item in the combo box, or when:
my own code updates the combo
box's SelectedItem to reflect that
the combo box is now displaying
properties for a different object.
I am interested in the SelectedIndexChanged event for case 1, so that I can update the current object's properties. But in case 2, I do not want the event to fire, because the object's properties have not changed.
An example may help. Let's consider that I have a list box containing a list of people and I have a combo box representing the nationality of the currently selected person in the list. Case 1 could happen if Fred is currently selected in the list, and I use the combo box to change his nationality from English to Welsh. Case 2 could happen if I then select Bob, who is Scottish, in the list. Here, my list update event-handler code sees that Bob is now selected, and updates the combo box so that Scottish is now the selected item. This causes the combo box's SelectedIndexChanged event to be fired to set Bob's nationality to Scottish, even though it already is Scottish.
How can I update my combo box's SelectedItem property without causing the SelectedIndexChanged event to fire? One way would be to unregister the event handler, set SelectedItem, then re-register the event handler, but this seems tedious and error prone. There must be a better way.
I created a class I called SuspendLatch. Offers on a better name are welcome, but it does what you need and you would use it like this:
void Method()
{
using (suspendLatch.GetToken())
{
// Update selected index etc
}
}
void listbox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (suspendLatch.HasOutstandingTokens)
{
return;
}
// Do some work
}
It's not pretty, but it does work, and unlike unregistering events or boolean flags, it supports nested operations a bit like TransactionScope. You keep taking tokens from the latch and it's only when the last token is disposed that the HasOutstandingTokens returns false. Nice and safe. Not threadsafe, though...
Here's the code for SuspendLatch:
public class SuspendLatch
{
private IDictionary<Guid, SuspendLatchToken> tokens = new Dictionary<Guid, SuspendLatchToken>();
public SuspendLatchToken GetToken()
{
SuspendLatchToken token = new SuspendLatchToken(this);
tokens.Add(token.Key, token);
return token;
}
public bool HasOutstandingTokens
{
get { return tokens.Count > 0; }
}
public void CancelToken(SuspendLatchToken token)
{
tokens.Remove(token.Key);
}
public class SuspendLatchToken : IDisposable
{
private bool disposed = false;
private Guid key = Guid.NewGuid();
private SuspendLatch parent;
internal SuspendLatchToken(SuspendLatch parent)
{
this.parent = parent;
}
public Guid Key
{
get { return this.key; }
}
public override bool Equals(object obj)
{
SuspendLatchToken other = obj as SuspendLatchToken;
if (other != null)
{
return Key.Equals(other.Key);
}
else
{
return false;
}
}
public override int GetHashCode()
{
return Key.GetHashCode();
}
public override string ToString()
{
return Key.ToString();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
parent.CancelToken(this);
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
// If it is available, make the call to the
// base class's Dispose(Boolean) method
//base.Dispose(disposing);
}
}
}
I think the best way would be to use a flag variable:
bool updatingCheckbox = false;
void updateCheckBox()
{
updatingCheckBox = true;
checkbox.Checked = true;
updatingCheckBox = false;
}
void checkbox_CheckedChanged( object sender, EventArgs e )
{
if (!updatingCheckBox)
PerformActions()
}
[Edit: Posting only the code is not really clear]
In this case, the event handler wouldn't perform its normal operations when the checkbox is changed through updateCheckBox().
I have always used a boolean flag variable to protect against unwanted event handlers. The TaskVision sample application taught me how to do this.
Your event handler code for all of your events will look like this:
private bool lockEvents;
protected void MyEventHandler(object sender, EventArgs e)
{
if (this.lockEvents)
{
return;
}
this.lockEvents = true;
//Handle your event...
this.lockEvents = false;
}
I let the event fire. But, I set a flag before changing the index and flip it back after. In the event handler, I check if the flag is set and exit the handler if it is.
I think your focus should be on the object and not on the event that's occuring.
Say for example you have the event
void combobox_Changed( object sender, EventArgs e )
{
PerformActions()
}
and PerformActions did something to the effect of
void PerformActions()
{
(listBox.SelectedItem as IPerson).Nationality =
(comboBox.SelectedItem as INationality)
}
then inside the Person you would expect to see something to the effect of
class Person: IPerson
{
INationality Nationality
{
get { return m_nationality; }
set
{
if (m_nationality <> value)
{
m_nationality = value;
this.IsDirty = true;
}
}
}
}
the point here is that you let the object keep track of what is happening to itself, not the UI. This also lets you keep track of dirty flag tracking on your objects, which could be useful for persistence later on.
This also keeps your UI clean and keeps it from getting odd event registration code that will most likely be error prone.
I have finally found a solution to avoid the uncessary event from being fired too many time.
I use a counter and I only hook/unhook the events I want to mask once when it is not needed, and when it is needed again.
The example below shows how I hide the CellValueChanged event of a datagrid.
EventMask valueChangedEventMask;
// In the class constructor
valueChangedEventMask = new EventMask(
() => { dgv.CellValueChanged += new DataGridViewCellEventHandler(dgv_CellValueChanged); },
() => { dgv.CellValueChanged -= new DataGridViewCellEventHandler(dgv_CellValueChanged); }
);
// Use push to hide the event and pop to make it available again. The operation can be nested or be used in the event itself.
void changeCellOperation()
{
valueChangedEventMask.Push();
...
cell.Value = myNewCellValue
...
valueChangedEventMask.Pop();
}
// The class
public class EventMask
{
Action hook;
Action unHook;
int count = 0;
public EventMask(Action hook, Action unHook)
{
this.hook = hook;
this.unHook = unHook;
}
public void Push()
{
count++;
if (count == 1)
unHook();
}
public void Pop()
{
count--;
if (count == 0)
hook();
}
}

How to Enable/Disable MenuItem and ToolButton together

I'm a newbie in C# bu I'm experienced Delphi developer.
In Delphi I can use same code for MenuItem and ToolButton using TAction.OnExecute event and I can disable/enable MenuItem and ToolButton together using TAction.OnUpdate event.
Is there a similar way to do this in C# without using external libraries? Or more - How C# developers share code between different controls?
Ok, may be I write my question in wrong way. I want to know not witch property to use (I know about Enabled property) but I want to know on witch event I should attach to if I want to enable/disable more than one control. In delphi TAction.OnUpdate event ocurs when Application is idle - is there similar event in C#?
Try the a modification of the command pattern:
public abstract class ToolStripItemCommand
{
private bool enabled = true;
private bool visible = true;
private readonly List<ToolStripItem> controls;
protected ToolStripItemCommand()
{
controls = new List<ToolStripItem>();
}
public void RegisterControl(ToolStripItem item, string eventName)
{
item.Click += delegate { Execute(); };
controls.Add(item);
}
public bool Enabled
{
get { return enabled; }
set
{
enabled = value;
foreach (ToolStripItem item in controls)
item.Enabled = value;
}
}
public bool Visible
{
get { return visible; }
set
{
visible = value;
foreach (ToolStripItem item in controls)
item.Visible = value;
}
}
protected abstract void Execute();
}
Your implementations of this command can be stateful in order to support your view's state. This also enables the ability to build "undo" into your form. Here's some toy code that consumes this:
private ToolStripItemCommand fooCommand;
private void wireUpCommands()
{
fooCommand = new HelloWorldCommand();
fooCommand.RegisterControl(fooToolStripMenuItem, "Click");
fooCommand.RegisterControl(fooToolStripButton, "Click");
}
private void toggleEnabledClicked(object sender, EventArgs e)
{
fooCommand.Enabled = !fooCommand.Enabled;
}
private void toggleVisibleClicked(object sender, EventArgs e)
{
fooCommand.Visible = !fooCommand.Visible;
}
HelloWorldCommand:
public class HelloWorldCommand : ToolStripItemCommand
{
#region Overrides of ControlCommand
protected override void Execute()
{
MessageBox.Show("Hello World");
}
#endregion
}
It's unfortunate that Control and ToolStripItem do not share a common interface since they both have "Enabled" and "Visible" properties. In order to support both types, you would have to composite a command for both, or use reflection. Both solutions infringe on the elegance afforded by simple inheritance.
You can enable or disable a control and all its children by setting its Enabled property.
You can hook the code for the MenuItem and the ToolButton in the same handler. For example:
menuItem.Click += HandleClick;
toolbarButton.Click += handleClick;
This way clicking both the MenuItem and the Button will execute the same code and provide the same functionality.

Categories

Resources