I have a simple WPF application that uses a "frame" for multi-page navigation. One of that pages creates a series of CheckBoxes and adds a couple of handlers (Checked/Unchecked) for each checkbox created. The CheckBoxes work as intended and are programmatically accessible, they can be checked or unchecked by click but none of the two events is ever fired if I click.
Here is the creation of the CheckBoxes:
ModuleStackpanels[i].Children.Add(ModuleCheckBoxes[i]);
StackPanel.SetZIndex(ModuleCheckBoxes[i], 2);
ModuleCheckBoxes[i].Checked += new RoutedEventHandler(ModuleCheckBoxClick);
ModuleCheckBoxes[i].Unchecked += new RoutedEventHandler(ModuleCheckBoxClick);
Where I go from 0 to 30. Then I have the handler:
private void ModuleCheckBoxClick(object sender, RoutedEventArgs e)
{
int CheckBoxCounter = 0;
for(int i=0;i<30;i++)
{
if (ModuleCheckBoxes[i].IsChecked == true) CheckBoxCounter++;
}
if(CheckBoxCounter > 1)
{
Button_QueryStatus.IsEnabled = false;
}
}
But nothing is fired.
Someone has got an idea?
Try to use CheckedChanged instead of Checked and Unchecked.
For example:
public bool checkedthecheckbox { get; set; }
CheckBox testchbox = new CheckBox();
private void Form1_Load(object sender, EventArgs e)
{
testchbox.CheckedChanged += new EventHandler(testchbox_CheckedChanged);
}
void testchbox_CheckedChanged(object sender, EventArgs e)
{
if (testchbox.Checked)
checkedthecheckbox = true;
else
checkedthecheckbox = false;
}
In your case:
ModuleStackpanels[i].Children.Add(ModuleCheckBoxes[i]);
StackPanel.SetZIndex(ModuleCheckBoxes[i], 2);
ModuleCheckBoxes[i].CheckedChanged += new EventHandler(ModuleCheckBoxClick);
private void ModuleCheckBoxClick(object sender, RoutedEventArgs e)
{
int CheckBoxCounter = 0;
for(int i=0;i<30;i++)
{
if (ModuleCheckBoxes[i].IsChecked == true) CheckBoxCounter++;
}
if(CheckBoxCounter > 1)
{
Button_QueryStatus.IsEnabled = false;
}
}
Good news! Not all the checkboxes had the event handler because of a fault in the creation of the buttons. 3 on 30 had it, and these buttons represented a different kind of item.
I just dealt with a similar issue on a WPF app that I did not write the front end for and here it came down to: Checked and similar event handlers will fire if the checkbox is triggered manually or programmatically. Other types are not guaranteed in the same way if you are changing the checkbox by setting to IsChecked.
ex. in my case, they attempted to use a Clicked event handler which would only fire from actual user interaction and not programmatic change, which makes perfect sense because setting the IsChecked status is truly not a click event (even though both can potentially check or uncheck the checkbox)
Related
I have a treenode which displays a checklist from a SQL database. I have a method to get the selected workflows.
I want to enable the run button if a checkbox is checked and disable the button if nothing is checked and on load.
I'm not sure where to put this if statement. I have tried putting it under the run button on the click action but it is not working correctly.
Any help is appreciated.
List<WorkflowViewModel> workflowViewList = new List<WorkflowViewModel();
var workflowList = GetSelectedWrokflows();
if (workflowList.Count == 0)
{
button.enabled = false;
}
else
{
button.enabled = true;
}
One way to do this is to create a method that will do the work of determining the selected workflow items and enabling or disabling the button. By putting the code in a single method, it allows you to call it from multiple places, and if you need to change the behavior, you only have one place to make the modifications.
Then you can just call this method from the Form_Load event, and from the checked list box's ItemCheck event:
public partial class Form1 : Form
{
List<WorkflowViewModel> workflowViewList = new List<WorkflowViewModel>();
private void SetRunButtonState()
{
workflowViewList = GetSelectedWorkflows();
button.Enabled = workflowViewList.Count > 0;
}
private void Form1_Load(object sender, EventArgs e)
{
SetRunButtonState();
}
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
SetRunButtonState();
}
// Rest of class code omitted...
}
I have absolutely no programmatic links or properties set such that my CheckedChanged fires as a result of anything except checking the radio button.
However, when I click a different, unrelated button, the button's click handler fires (this is expected). In this click handler, the button disables itself (it re-enables on a different button's click), which then triggers myRadioButton_CheckedChanged handle for an unrelated radiobutton fires.
The call stack that I'm seeing is essentially
myRadioButton_CheckedChanged (...)
myButton_Click(...)
Main(...)
The line in myButton_Click that is triggering the myRadioButton_CheckedChanged is apparently
myButton.Enabled = false;
The related code is:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
// L-R
if (radioButton1.Checked == true)
{
orientation_left = 3;
pictureBox2.Invalidate();
Debug.Print("left {0}", orientation_left);
}
}
private void select1_Click(object sender, EventArgs e)
{
Debug.Print("select1click");
if (select1Down == false)
{
// ... stuff
select1.Enabled = false; // Causing the CheckedChanged to fire
select2.Enabled = false;
select1Down = true;
}
}
Ok, got it.
Check the TabOrder on your Button and RadioButton.
Seems that when you disable the Button, the focus is shifted to the next control, which is probably your RadioButton, causing it to become checked.
On my test From, all I had to do was to make sure that the RadioButton's TabOrder was not right after the Button.
Cheers
EDIT:
This seems to be a known problem as I just found this MSDN thread: http://social.msdn.microsoft.com/Forums/windows/en-US/77fbec3b-1f63-42e1-a200-19b261b63794/the-radiobutton-clicked-event-is-fired-without-the-radio-button-beeing-clicked-?forum=winforms
Okay, it's kinda hacky but it works without changing anything to the tab order:
private void select1_Click(object sender, EventArgs e)
{
if (!select1Down)
{
// ... stuff
SendKeys.SendWait("{Tab}");
select1.Enabled = false;
select2.Enabled = false;
select1Down = true;
}
}
How to check the box dynamically without firing check changed function? I have 20 checkboxes that are dynamically created and I have a drop-down that determines how many checkboxes are to be checked.
If I selected 3 and click on 6th check box, that should check checkboxes 9, 7 and 8. In this process I don't want to fire checkchanged function.
CheckBox cb1 = (CheckBox)sender;
selectedbox = int.Parse(cb1.Name);
for (int i = 1; i < selectedquantity; i++)
{
premiumticket[selectedbox].Checked = true;
//here check changed firing i dont want that
selectedbox++;
}
You can't stop CheckBox from firing event when it's state changed. Consider to either unsubscribe from event when you don't need it:
for (int i = 0; i < selectedquantity; i++)
{
premiumticket[selectedbox + i].CheckedChanged -= checkBox_CheckedChanged;
premiumticket[selectedbox + i].Checked = true;
premiumticket[selectedbox + i].CheckedChanged += checkBox_CheckedChanged;
}
or use some flag to omit handling of event if you don't need it:
flag = false;
for (int i = 0; i < selectedquantity; i++)
premiumticket[selectedbox + i].Checked = true;
flag = true;
And in handler:
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
if (!flag)
return;
//...
}
I can't see really solution how not to fire the event. You could disable the event with -= and then add it again with +=.
checkBox.CheckedChanged -= checkBox_CheckedChanged;
checkBox.Checked = true;
checkBox.CheckedChanged += checkBox_CheckedChanged;
The big disadvantag of this is that you would have to fire the event manually if you would like to have this event once, when you're updating the values.
I'd rather set a flag in the class and check this flag in the update code.
Remove the event attached then attach it after the you change the check :
{
cb1.CheckedChanged -= new EventHandler(cb1_CheckedChanged);
premiumticket[selectedbox].Checked = true;
cb1.CheckedChanged += new EventHandler(cb1_CheckedChanged);
}
private void cb1_CheckedChanged(object sender, EventArgs e)
{
// Some COde
}
Re-subscribing (unsubscribing/subscribing) technique is not very nice, because you have to deal with every event handler, making it common, adding flags, etc.
What is really simple to do is to use another event - Click - to simply check changes to the control which are made by user:
private void checkBox1_Click(object sender, EventArgs e)
{
checkBox2.Checked = checkBox1.Checked;
checkBox3.Checked = false;
}
private void checkBox2_Click(object sender, EventArgs e)
{
// this is not called when you set "Checked" programmatically
}
It is obvious, what you have to implement different pattern, to actually do something with data (save them or react on changes), if they are changed programmatically. In above example, clicking checkBox2 will run handler, where you, to example, save something into configuration, while setting checkBox2.Checked = true, when clicking checkBox1, will not.
It may happens, what for some CheckBox'es you will use only Click, for others - only CheckedChanged.
Yesterday I try to implement a new listview that support sub-item edit, my solution is to show a textbox when double click the sub-item. The key code as following:
protected override void OnDoubleClick(EventArgs e)
{
Point pt = this.PointToClient(Cursor.Position);
ListViewItem curItem;
int subItemIndex = GetSubItemAt(pt.X, pt.Y, out curItem);
DoubleClickEventArgs args = new DoubleClickEventArgs(subItemIndex);
base.OnDoubleClick(args);
if (subItemIndex>=0 && !args.Cancel)
{
//StartEdit(...);
}
}
public void EndEdit(bool acceptChanges)
{
//validation
.................
.................
AfterSubItemEventArgs e = new AfterSubItemEventArgs(this.SelectedItems[0], m_editSubItemIndex, this.SelectedItems[0].SubItems[m_editSubItemIndex].Text, m_textbox.Text, false);
OnAfterSubItemEdit(e);
if (e.Cancel)
{
//....
}
else
{
//set new value
}
m_textbox.Visible = false;
m_editSubItemIndex = -1;
}
OnAfterSubItemEdit is a event that user can do some validations or other operations. I add a check in this method, if the new value exist, I will show a messagebox to user firstly, then hide the textbox. But now, the problem comes, when i move the mouse, the listview items can be selected, I don't how to solve this issue, I tried my best to find out the way, but failed. So, please help me!
Listview has a LabelEdit property; when you set it "true", then in an event handler you can call Listview.Items[x].BeginEdit(), and edit an item. As an example, you can handle ListView.DoubleClick event and call BeginEdit right there:
private void Form1_Load(object sender, System.EventArgs e)
{
listView1.LabelEdit = true;
}
private void listView1_DoubleClick(object sender, System.EventArgs e)
{
if(this.listView1.SelectedItems.Count==1)
{
this.listView1.SelectedItems[0].BeginEdit();
}
}
The problem is that your form still calls the DoubleClick event whether the value exists or not. Add appropriate condition before calling base DoubleClick in your code, i.e.:
if(!new value exists)
base.OnDoubleClick(args);
In my project, There are two radioButtons. To which I have given same CheckedChanged event by doing
something like this:
DoctorRadioButton.CheckedChanged += new EventHandler(RadioButton_CheckedChanged);
PatientRadioButton.CheckedChanged += new EventHandler(RadioButton_CheckedChanged);
I kept both the RadioButtons in a Panel to make them one true while other one is false.
Now the problem is that I am implementing a very big code in the RadioButton_CheckedChanged event.
Whenever the user is changing the state of any of the two RadioButtons, the event is raising two times.
After so many hours I got the answer, the event is raising two times because both the RadioButton states are being changed(Hence, the event will be raised two times). To solve this problem I am trying to unhook the event temporarily something like this:
RadioButton_CheckedChanged Event: (Not Working)
if (DoctorRadioButton.Checked)
{
PatientRadioButton.CheckedChanged -= RadioButton_CheckedChanged; //Un
//
//My functions
//
PatientRadioButton.CheckedChanged += new EventHandler(RadioButton_CheckedChanged);
}
else
{
DoctorRadioButton.CheckedChanged -= RadioButton_CheckedChanged;
//
//My functions
//
DoctorRadioButton.CheckedChanged += new EventHandler(RadioButton_CheckedChanged);
}
Eventhough the event is executing two times. I know I am doing something wrong in Hooking and Unhooking. Please Help.
You can check the sender RadioButton and place your code accordingly like this -
void RadioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton senderRadioButton = sender as RadioButton;
if (senderRadioButton.Equals(DoctorRadioButton))
// OR senderRadioButton.Name == "DoctorRadioButton"
{
// Place your code here for DoctorRadioButton.
}
else
{
// Place your code here for PatientRadioButton.
}
}
Update
If you can't use two different handlers for both radioButtons and want to execute code only in case checkbox is checked you can do this -
void RadioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton senderRadioButton = sender as RadioButton;
if (senderRadioButton.IsChecked)
{
// Place your code here for check event.
}
}
For an extremely simple (albeit crude) solution would be to not hook both the radio buttons, and hook only one of them to the handler: since checking one radio unchecks the other one, it would work as intended.
A more complicated way would be to use a backing property, like this:
class myForm
{
private bool radioStatus = false; // depends on the default status of the radios
private bool RadioStatus
{
get{return radioStatus;} set {radioStatus = value; Checked_Changed();}
}
public myForm()
{
// Lambdas as handlers to keep code short.
DoctorRadioButton.CheckedChanged += (s,args)=>
{ if((s as RadioButton).Checked) RadioStatus = true; };
PatientRadioButton.CheckedChanged += (s,args)=>
{ if((s as RadioButton).Checked) RadioStatus = false; };
}
void Checked_Changed()
{
if (RadioStatus) // = true --> DoctorRadioButton was checked
{
//code
}
else // = false --> PatientRadioButton was checked
{
//other code
}
}
}
This approach has the advantage of allowing you to abstract from the UI a bit.
Put both radio buttons in the same panel or groupbox and automatically they will be grouped so that only one can be selected at a time.
Its a late solution but i found there is no correct answer for your question so i am posting it may be it works For You
Create Click Event for both radio button and simple put your code beacuse on every click your radio button got checked and your code executes :):):)
private void DoctorRadioButtons_Click(object sender, EventArgs e)
{
//Your code on Doctor Radio Button
}
private void PatientRadioButton_Click(object sender, EventArgs e)
{
// Your code on Patient Radio Button
}