I need to disable all execution of any event (click) for a period of time after l click a button. At that particular period, no matter how many buttons I click the functions of buttons will not be executed. I cannot use the Thread.Sleep() because it only delays the execution, the function of the button still being executed. Does any1 can help? My code is here:
int delay = 2000; //unusable as it is just delaying the execution of clicked button.
public void PressCOM(string key)
{
if (key == "PressSc")
{
PressAndRelease(key);
PressAndRelease("C");
Thread.Sleep(delay);
}
Sleeping on the main thread is a bad idea anyway.
You will have to built in some logic concerning the buttons to either:
disable them
ignore clicks
Use a Boolean property that is reset by a timer.
Disabling and showing a "Please Wait..." kind of message to the user will be a better option...
You can Disable and enable the panels .Grids in WPF as you like
I Usually use a Adorner Overlay (translucent) with a message to stop user from interacting with the UI... usually Backround worker helps to Show and Hide the overlay when required.
This will be a Good Artice for Adorner implemtation in XAml
hope it helps.. :)
It's not really clear what you want to do.
It's not a really good idea to put a sleep in the main application thread. It will make your application unresponsive to all Windows messages (both originated by user or by Windows itself). Your users will fill it hanged.
If you need to disable only that button you may set its IsEnabled property to false, user won't be able to click it.
If you want to disable all events you can use the IsEnabled property of the window itself.
If to disable all controls (or just one button) isn't the right solution for you then you may use one of the followings.
Add a state variable (or a simple flag). In all your event handlers you'll check if that variable is true or not (you'll change it with a timer). Something like:
if (!_canHandleMouseClicks)
return false;
Disable all buttons and re-enable them after a period of time:
private static IEnumerable<Button> FindAllButtons(DependencyObject obj)
{
if (obj == null)
return null;
int childrenCount = VisualTreeHelper.GetChildrenCount(obj);
for (int i = 0; i < childrenCount; ++i)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is Button)
yield return (Button)child;
// If you may have buttons inside buttons then uncomment these lines
//foreach (Button childOfChild in FindAllButtons(child))
// yield return childOfChild;
}
}
Then you can write:
foreach (Button button in FindAllButtons(window))
button.IsEnabled = false; // true to re-enable
A possible solution might be to show a dialog and hide the dialogs ok, cancel and close buttons. This will prevent any button from being clicked in the main-window.
Related
i have a little Problem with my treeview.
Background: I have a treeview with multiple Items in it, whenever you click on a Parent or first child an Event should fire where a new window opens where you can do some stuff.
I am using the "After_Select" event of the tree view as following:
if (_inside) //this boolean was my first attempt to deal with the problem
{
if (treeView1.SelectedNode.Parent != null)
{
if (treeView1.SelectedNode.Parent.Parent != null)
{
//its 2nd child -> do nothing
}
else
{
Configuration_New_Click(treeView1.SelectedNode.Parent.Name.ToString(), treeView1.SelectedNode.Name.ToString()); //its 1st child do something
}
}
else
{
Configuration_New_Click(treeView1.SelectedNode.Name.ToString(), ""); //its parent, do something else
}
}
The Problem: The Event fires everytime i for example tab out of the program and tab back in -> the first item in the treeview gets selected -> AfterSelect fires. I have some more situations like this, basically the event does what it should, it fires whenever an item was selected. The problem is the first treeview item gets selected whenever the treeview looses focus by switching windows for example. (it only fires if i clicked a other treeview item than the first before doing so)
I read a bit in the forum and found a solution i tried -> set a boolean to false whenever it should not trigger. it works with some Problems but the event still triggers when i alt+tab to other windows and alt tab back to back programm. is there any quick and dirty solution to handle this?
Thanks for your time and effort!
Edit: Is the "MouseDown" a better solution? and if so, how can i use this event with my code? since i need the selectedNode in order to run the code above?
Regards,
Christian
I am trying to create a reusable Settings dialog and I want to bind the controls in the dialog to the Properties.Settings built into Visual Studio.
This is the code I use to bind each control as I iterate through them:
Control.DataBindings.Add(new Binding(strProperty, Properties.Settings.Default, Control.Name, false, DataSourceUpdateMode.Never));
Where strProperty is resolved to the appropriate Property of the control to bind with. Note the update mode: DataSourceUpdateMode.Never. More on that in a minute.
This code works to bind the control to the setting. When the dialog opens, all the controls display the appropriate values. The problem is with getting the DataSource, i.e. the Properties.Settings, to update properly, and at the right time. When the DataSourceUpdateMode is set to "OnPropertyChanged", it works as expected to update the values, but this isn't the desired behavior of a dialog. You don't want to update until the OK button is pressed, not as soon as the value in the control has changed.
After reading all the documentation I could find, it seemed to me that the best way would be set the DataSourceUpdateMode to "Never" and then when the OK button is pressed I would iterate through all of the controls and call Control.DataBinding[0].WriteValue() to manually update all the properties. But when I did that I found that after the first control was updated, every single one of the remaining controls would immediately revert to it's previous value!
public void UpdateDataSource(Control.ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl.Controls.Count > 0)
{
UpdateDataSource(ctrl.Controls);
}
if (ctrl.DataBindings != null)
{
foreach (Binding binding in ctrl.DataBindings)
{
binding.WriteValue();
}
}
}
}
I also tried something using the DataSourceUpdateMode.OnValidation flag. I set every control's CausesValidation property to false to prevent updates from occurring before the OK button is pressed. Then when the OK button is pressed I iterate through all the controls and set the CausesValidation flag back to true and then call the form's ValidateChildren() method. This has the desired effect of causing the validation to occur on all of the controls after, and only after the OK button is pressed but the result is exactly the same as when I used the binding.WriteValue(). Immediately after the first control updates the data source, every other bound control on the form reverts back to its original value.
I have a method that shows a window and then returns the value of the button clicked. What I have done is that when I click the button I change a variable and then the variable will be returned. What I need is someway to pause the method until the variable has been changed.
I program a game in unity and it's using mono.
Code:
public virtual Buttons Execute(){
this.holder.SetActive(true); //Set the window active
// Here wait for the user to click a button
return clicked;//Returns the button clicked.
}
The code that handles the user interface is event driven, so the sensible thing to do would be to use an event instead of using a method like you try to do.
It's possible to create a method that works that way, but you have to create your own message pump that runs while you are waiting:
public virtual Buttons Execute(){
this.holder.SetActive(true); // Set the window active
clicked = null; // Set the state as undetermined
while (clicked == null) { // Wait until it is set
Application.DoEvents(); // Process messages
Thread.Sleep(10); // Wait for a while
}
return clicked; // Returns the button clicked.
}
You can read in the question Use of Application.DoEvents() for explanations of the pitfalls of using DoEvents this way.
I have a problem while doing this in the code-behind file of a winform :
// Waiting Cursor + disabling form
Cursor = Cursors.WaitCursor;
this.Enabled = false;
// Synchronous method
SomeWork();
// Re-enabling form
Cursor = Cursors.Default;
this.Enabled = true;
Current Behaviour
Clicking on a button for example during Somework() will execute the method associated to the button after re-enabling the form.
Expected Behaviour
I don't expect from the form to store the clicking events of the user while the form is disabled.
Question
Is there a way to empty the Clicking cache of the form (So that I'd do it before re-enabling the form) ?
IMPORTANT EDIT
A possible easy solution would be implementing the IMessageFilter interface in the code behind of the form. Disabling the left seems easy using this PreFilterMessage :
public bool PreFilterMessage(ref Message m)
{
// Blocks all the messages relating to the left mouse button.
return (m.Msg >= 513 && m.Msg <= 515) ;
}
But once again, disabling and re-enabling the mouse's left clicks DOES NOT EMPTY THE MOUSE BUFFER ...
The problem is that the process is running in the same thread, so the form doesn't actually get disabled before the process starts running. The easy thing to do would be use Application.DoEvents() to force it to set everything to disabled before starting the process, but the more professional (and probably safer) method is to run the time-consuming process in another thread.
NOTE: After running into another hitch in my own programming I found that you may have to run Application.DoEvents() before enabling everything again--it will fire any clicks the user made on the disabled controls, instead of waiting for the process to complete--enabling the controls--and THEN firing the click.
Obviously DoEvents is messy and I should be using threads.
I am currently trying to create a program that will show a slideshow of pictures from an ImageList with variable show times from a ListView, which is acessed through a numericUpDown, but when I click the button to start, nothing happens, until the time of the slideshow ends, where the last slide is shown, then disappears straight away (if i leave out "pictureBox1.Visible = false" at the end, it stays).
current code:
private void buttonSlideshow_Click(object sender, EventArgs e)
{
pictureBox1.Visible = true;
for (int s = 0; s < listView1.Items.Count; s++)
{
listView1.Items[s].Selected = true;
pictureBox1.Image = imageList1.Images[s];
DateTime later = DateTime.Now.AddMilliseconds((double)numericUpDown1);
while (DateTime.Now < later)
{
}
}
pictureBox1.Visible = false;
}
I have tried many versions of this (including using timers and switching code around) have no idea what is going wrong
numericUpDown1 is the duration of the slide, have been using integers for testing, still doesn't work
Doing this:
while (DateTime.Now < later)
Is blocking your UI thread. It can't redraw the screen while you are keeping it busy spinning it's wheels. Use a timer with a call back instead.
You'll need to rework your code slightly. Rather than use a for loop, define a variable for your current slide, initialize it to zero in your click handler, make your picture box visible, load the first picture and then start your timer.
In your timer handler, you'll increment the current index, check it against the length of you list of slides and, if you still have slides to display, load the next one and then start the timer again (or you can use a timer that fires repeatedly, although you might want to be careful that it doesn't fire again before you're done handling that last one). If there are no more slides left, just do you clean up and make your picture box invisible again.
One final note, be careful with which thread the timer is going to fire on. In win forms you can use System.Windows.Forms.Timer which fires on the UI thread and you won't have any problems. In WPF you can use DispatcherTimer which also fires on the UI thread. Other timers generally run in their own thread and you'll have to handle pushing anything that's supposed to update the UI back to the UI thread.