How do I repetitively perform an action when the mouse left button is pressed and held down in WPF?
The following event handler for the UIElement.PreviewMouseLeftButtonDown event does not get the job done:
private void BaseButtonRight_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// keep performing action while mouse left button is pressed.
// Checking e.ButtonState works only for one click
}
Execution does not even get into the while loop and handler is called when the left mouse button is released!
Why not use a RepeatButton?
http://msdn.microsoft.com/en-us/library/ms746649(v=vs.85).aspx
Start a BackroundWorker which exits when the mouse has been released. Set a flag with the mouse up event and also check periodically in the BackgroundWorker DoWork function. Make sure you use lock { } around accessing the flag.
Edit: in case you want to access something on the UI thread, use Dispatcher.BeginInvoke, for example:
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
ComboBoxItem selItem = ComboboxConnectString.SelectedItem as ComboBoxItem;
if (selItem != null && selItem.Tag is string)
ComboboxConnectString.Text = (string)selItem.Tag;
}));
Run a thread until MouseLeftButtonUp is fired.
Related
I have a RadDropDownList in suggestappend mode and a usercontrol as keyboard, this have buttons with ControlStyles.Selectable = false. the MouseUp event fires a SendKeys.Send(key).
The thing is when I focus in the RadDropDownList and write with my keyboard (UserControl) the suggest list appears for a milisecond and desappear.
I tried to control the popup event but it seems to have nothing to do with the suggest list.
how can i keep it opened showing suggestions until user leaves the RadDropDownList?
Here is how to access the auto complete suggest popup and cancel the closure of the popup:
radDropDownList1.DropDownListElement.AutoCompleteSuggest.DropDownList.PopupClosing += DropDownList_PopupClosing;
. . .
void DropDownList_PopupClosing(object sender, Telerik.WinControls.UI.RadPopupClosingEventArgs args)
{
args.Cancel = true;
}
I'm using WPF to design a borderless, movable application window.
In order to manually perform the ability to drag and drop the window, I've added an OnMouseDown event to the <Window> element, that executes a corresponding C# function (this.DragMove()).
Additionally, I need an <Image> button to allow some operation (with the OnMouseUp event this time). Note that it has to be an Image tag, and not a Button.
Unfortunately, the Image event fired only when the right mouse button is clicked, probably because the left button is held to the window event. Am I right?
When someone clicks the Image button, I want only the Image event to be triggered. How can I do it?
Problem you're facing is most probably related to event routing. The idea is that if your handler doesn't mark event as a Handled it will be routed to the next listener unless reach end of chain or one of listeners/handlers will set it as Hadnled.
So if you have MouseDown event handler for both Window and Image you should keep in mind that routing will stop at a point when you will set e.Handled = true;:
private void Window_OnMouseDown(object sender, KeyEventArgs e)
{
e.Handled = false; // will NOT break event chain;
}
You can always check a type of sender so it will make possible for you to differ Image and Window events:
private void Image_OnMouseDown(object sender, KeyEventArgs e)
{
if (sender is Image)
{
// Handle Image.MouseDown
e.Handled = true; // we don't need to push event further;
}
}
Its because of WPF bubbling and tunnelling events. so what u can do is whenever u handle event on button use bubbling for that means you can use previewevents for that for both button and window and whenever you just want to handle event for button then after last line of code in button click just write down like this.
e.handled=true;
// here e is the event argument which u will get in your preview event.so now window dragging event will not work.
i would just suggest first clear the idea of bubbling(preview mouse event) and tunneling in wpf.
Difference between Bubbling and Tunneling events
and go through some of the example of bubbling and tunnelling. you will get better idea.
http://www.codeproject.com/Articles/464926/To-bubble-or-tunnel-basic-WPF-events
I have a simple WPF button and a textbox in my WPF application(not using MVC or binding at all). I like to be able to do the following upon clicking the button:
1) Clear the textbox
2) Create the result
3) assign the result to the textbox
I used Textbox.Clear, TextBox.Text= String.Empty, delegates and a dispatcher approach like
private void button_Click(object sender, RoutedEventArgs e)
{
Application.Current.Dispatcher.BeginInvoke(new Action (ClearReportTxtBox), DispatcherPriority.Send);
System.Threading.Thread.Sleep(5000);
runTest();
}
private void ClearReportTxtBox()
{
Report_textBox.Text = string.Empty;
}
None of them working correctly for me. The dispatcher method is somehow working but not as I wish. It seems that the Clear task will be queued and when the all actions in the button click handler are finished, it will come into play and delete the textbox, but this causes that the generated report and already assigned to the textbox (created by runtest in the code above) will be deleted as well. Hence it is too late delete action and eliminate the whole result.
Currently it seems to me that by clicking on the button the UIthread blocks and takes the control. The Dispatcher will queue the delete action as next action after finishing the button click.
Is it possible to force delete at the beginning and then do the rest? What I like to reach is that I pause the button activity and do delete at first action and then continue with the rest of actions in the button handler.
Am I doing something wrong?
Thank you for your help in advance.
The "Dispatcher.BeginInvoke" is kinda weird for what you want to do
All the UI update has to be done on main thread. Since the "Button_click" event is executing on main thread, the delegate you push into Dispatcher can only be executed AFTER the button_click handle is completed. That's why the execution sequence becomes
1. The GUI freeze because Thread.Sleep
2. RunTest
3. ClearReportTextBox
Guess you can try sth like the following instead.
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ClearReportTxtBox();
Task.Factory.StartNew(RunTest);
}
private void ClearReportTxtBox()
{
MyTextBox.Text = string.Empty;
}
private void RunTest()
{
System.Threading.Thread.Sleep(5000);
if (dispatcher != null && !dispatcher.CheckAccess())
{
dispatcher.Invoke(priority, ()=> MyTextBox.Text = "123");
}
else
{
MyTextBox.Text = "123";
}
}
I creating a custonmized box class (inherits from ComboBox). I don't want the text box to react to right mouse clicks. I can get rid of the context menu by setting this to null in ApplyTemplate, but right mouse clicks move the cursor. I tried hooking up PreviewMouseRightButtonDown in ApplyTemplate and setting Handled to True, but the event still gets through which is strange as it seems to work for the left click.
The cursor actually moves when the mouse button is released, so you want mark the MouseRightButtonUp event as handled. You could override OnMouseRightButtonUp:
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
base.OnMouseRightButtonUp(e);
e.Handled = true;
}
Or you could attach a class handler to the MouseRightButtonUp event to mark it as handled:
static MyComboBox()
{
EventManager.RegisterClassHandler(
typeof(MyComboBox),
MouseRightButtonUpEvent,
new MouseButtonEventHandler(MyComboBox_MouseRightButtonUp));
}
private static void MyComboBox_MouseRightButtonUp(
object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
That will also prevent the context menu from being created without you having to set it to null explicitly.
How to remove all the associated in built events of a control in WPF?
There is no easy way to remove all events queued on the Dispatcher. Even if there were, you wouldn't want to do so because it would break many WPF controls that rely on background events to update their data structures and UI.
However, there is an easy way to discard selected input events from the queue, such as keyboard, mouse and stylus events:
Create a "FlushInputQueue" method that registers an event handler with InputManager.PreprocessInput, invokes a DispatcherOperation at Input priority, then removes the event handler.
When the PreprocessInput event fires, check the input message and set the Handled flag to true if you want to discard it.
Here is some code to get you started:
public void FlushInputQueue()
{
PreProcessInputEvent handler = (obj, e) =>
{
if(ShouldFlushEvent(e.StagingItem.Input))
e.StagingItem.Input.Handled = true;
};
InputManager.PreProcessInput += handler;
Dispatcher.Invoke(DispatcherPriority.Input, new Action(() => {}));
InputManager.PreProcessInput -= handler;
}
private bool ShouldFlushEvent(InputEventArgs e)
{
// Example only:
return e is MouseEventArgs || e is KeyboardEventArgs || e is StylusEventArgs;
}
The ShouldFlushEvent method should probably be customized for your particular scenario to avoid throwing out events that should be kept.
One last thought: Have you considered doing your long-running operation on a background thread so the UI remains responsive? Many times this is a better solution than locking the UI when an item is clicked on, and removes any reason for wanting to flush the queue.