Silverlight MouseLeftButtonDown event not firing - silverlight

I can get MouseEnter, MouseLeave, and Click events to fire, but not MouseLeftButtonDown or MouseLeftButtonUp.
Here's my XAML
<UserControl x:Class="Dive.Map.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Canvas x:Name="LayoutRoot" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown">
<Button x:Name="btnTest" Content="asdf" Background="Transparent" MouseLeftButtonDown="btnTest_MouseLeftButtonDown"></Button>
</Canvas>
</UserControl>
And here's my code
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void btnTest_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
btnTest.Content = DateTime.Now.ToString();
}
private void LayoutRoot_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
e.Handled = false;
}
}
What am I doing wrong?

The Button control (or more specifically the ButtonBase super-class from which it derives) handles the MouseLeftButtonDown event itself in order to generate the Click event. Hence you cannot get a MouseLeftButtonDown event from the standard Button.
Is there a reason you aren't using the Click event?

If you add the handlers with code like this:
dgv.AddHandler(DataGrid.MouseLeftButtonDownEvent, new MouseButtonEventHandler(dgv_MouseLeftButtonDown), true);
dgv.AddHandler(DataGrid.MouseLeftButtonUpEvent, new MouseButtonEventHandler(dgv_MouseLeftButtonUp), true);
and make sure you pass true in the last argument "HandledEventsToo" I think you will get it to work - I did...

Have you ever noticed that the MouseLeftButtonDown and MouseLeftButtonUp events are not fired when a Silverlight button is clicked? The reason for this is that the button handles these two events itself by overriding the OnMouseLeftButtonDown and the OnMouseLeftButtonUp handlers. In the OnMouseLeftButtonDown override, the Click event is raised and the MouseLeftButtonDown event is marked as handled so it couldn't bubble in the visual tree. The OnMouseLeftButtonUp override also marks the MouseLeftButtonUp as handled.
This thing can be changed using the ClickMode property of the Button control. It has the following values - Hover, Press, Release. The default one is Pressed and we have already explained it. When we have ClickMode set to Release, the Click event will be raised in the OnMouseLeftButtonUp override and the MouseLeftButtonDown and MouseLeftButtonUp events will be handled inside the button again. If we set the ClickMode to Hover, the Click event will be raised with the MouseEnter event and we will also be able to use the mouse button events.

Related

LostFocus event of a window isn't firing

I have a window:
<Window ...
LostFocus="SpecialLettersLayout_OnLostFocus">
....
</Window>
In this window I have a canvas, and in it I have a Path object which has a non-rectangular form.
In this window I call the LostFocus event. In the .xaml.cs file for that window, I define the SpecialLettersLayout_OnLostFocus event:
private void SpecialLettersLayout_OnLostFocus(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
In my application I have a window and when I click on a button, this window is opened. This window is smaller than the background window, so that means that the background window is still visible.
When I click on the background window I want to hide the small window, because its focus is lost. However, the SpecialLettersLayout_OnLostFocus event isn't hit. Why is that happening?
The LostFocus event is used for logical focus. What you need here is a physical focus which has another name called LostKeyboardFocus.
Logical focus involves using of FocusManager. I'm not really sure when LostFocus is triggered but it's not the traditional LostFocus you thought. Instead we have to use LostKeyboardFocus. Also you may have to change your handler to suit the LostKeyboardFocus event. The handler type is KeyboardFocusChangedEventHandler.
In the end what helped me was the Deactivated event, which didn't work in combination with ShowDialog(), so I used it with Show() instead.

XAML Window MouseDown event beats Image event

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

wpf catching mouse down outside my custom control

I'm building a custom control in WPF. I want to catch a mouse down event when my control is in focus but the user clicks outside the control. Is there a way to do that and if so how?
My control inherits from ListBox.
You can use UIElement.CaptureMouse and it's partner UIElement.ReleaseMouseCapture to capture all mouse events to a single control, regardless of what the mouse was over when the event occurred.
In your example I would capture the mouse when the control has focus, and release the mouse when the control looses focus.
Suppose you have a Window with a TextBox on it.
By registering to Window's MouseDown event,
MouseDown += new MouseButtonEventHandler(Window_MouseDown);
You can use following code
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (TextBox1.IsFocused)
{
MessageBox.Show("TextBox1 in focus.");
}
}
To catch this event if TextBox1 is in focus.

WPF- Is it possible to add an OnVerticalOffsetChanged event to a custom textbox?

Is there any way for me to do this?
You can tell when the VerticalOffset changes by adding a handler to the ScrollViewer.ScrollChanged event to your TextBox. Something like this:
<TextBox AcceptsReturn="True" ScrollViewer.ScrollChanged="TextBox_ScrollChanged" />
The TextBox uses a ScrollViewer internally, so it's ScrollChanged event will bubble up to the TextBox (where you can handle it). The event arguments include information about what changed, such as the VerticalChange (the amount that the control has scrolled vertically).
private void TextBox_ScrollChanged(object sender, ScrollChangedEventArgs e) {
System.Diagnostics.Debug.WriteLine(string.Format("************ {0}", e.VerticalChange));
}

How to capture a mouse click on an Item in a ListBox in WPF?

I want to get notified when an item in a ListBox gets clicked by the mouse, whether it is already selected or not.
I searched and found this: (http://kevin-berridge.blogspot.com/2008/06/wpf-listboxitem-double-click.html see the comments)
private void AddDoubleClickEventStyle(ListBox listBox, MouseButtonEventHandler mouseButtonEventHandler)
{
if (listBox.ItemContainerStyle == null)
listBox.ItemContainerStyle = new Style(typeof(ListBoxItem));
listBox.ItemContainerStyle.Setters.Add(new EventSetter()
{
Event = MouseDoubleClickEvent,
Handler = mouseButtonEventHandler
});
}
//Usage:
AddDoubleClickEventStyle(listView1, new MouseButtonEventHandler(listView1_MouseDoubleClick));
This works, but it does it for a DoubleClick. I can't get it working for a single click though. I tried MouseLeftButtonDownEvent - as there doesn't seem to be a MouseClick event, but it's not being called.
A bit more general side question: How can I see what events do exist and which handlers correspond to them and when they actually do something? For example, what tells me that for a MouseDoubleClickEvent I need a MouseButtonEventHandler? Maybe for a MouseLeftButtonDownEvent I need some other handler and that's why it's not working?
I also tried subclassing ListBoxItem and override OnMouseLeftButtonDown - but it doesn't get called either.
Marc
I believe that your MouseLeftButtonDown handler is not called because the ListBox uses this event internally to fire its SelectionChanged event (with the thought being that in the vast majority of cases, SelectionChanged is all you need). That said, you have a couple of options.
First, you could subscribe to the PreviewLeftButtonDown event instead. Most routed events have a routing strategy of Bubbling, which means that the control that generated the event gets it first, and if not handled, the event works its way up the visual tree giving each control a chance at handling the event. The Preview events, on the other hand, are Tunneling. This means that they start at the root of the visual tree (generally Window), and work their way down to the control that generated the event. Since your code would get the chance to handle the event prior to the ListBoxItem, this will get fired (and not be handled) so your event handler will be called. You can implement this option by replacing MouseDoubleClickEvent in your sample with PreviewMouseLeftButtonDown.
The other option is to register a class handler that will be notified whenever a ListBoxItem fires the MouseLeftButtonDown event. That is done like this:
EventManager.RegisterClassHandler(typeof(ListBoxItem),
ListBoxItem.MouseLeftButtonDownEvent,
new RoutedEventHandler(this.MouseLeftButtonDownClassHandler));
private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
}
Class Handlers are called before any other event handlers, but they're called for all controls of the specified type in your entire application. So if you have two ListBoxes, then whenever any ListBoxItem is clicked in either of them, this event handler will be called.
As for your second question, the best way to know what type of event handler you need for a given event, and to see the list of events available to a given control, is to use the MSDN documentation. For example, the list of all events handled by ListBoxItem is at http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem_events.aspx. If you click on the link for an event, it includes the type of the event handler for that event.
There is also another way - to handle PreviewMouseDown event and check if it was triggered by the list item:
In XAML:
<ListBox PreviewMouseDown="PlaceholdersListBox_OnPreviewMouseDown"/>
In codebehind:
private void PlaceholdersListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var item = ItemsControl.ContainerFromElement(sender as ListBox, e.OriginalSource as DependencyObject) as ListBoxItem;
if (item != null)
{
// ListBox item clicked - do some cool things here
}
}
Was inspired by this answer, but it uses listbox by name, I propose to use sender argument to avoid unnecessary dependencies.
I think the first option in Andy's answer, of using PreviewMouseLeftButtonDown, is the way to go about this. In XAML it would look like this:
<ListBox Name="testListBox">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter
Event="PreviewMouseLeftButtonDown"
Handler="ListBox_MouseLeftButtonDown" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
There is another way to get MouseDown event in ListBox. You can add event handler for events that are marked as handled by using handledEventsToo signature of AddHandler method:
myListBox.AddHandler(UIElement.MouseDownEvent,
new MouseButtonEventHandler(ListBox_MouseDown), true);
Third parameter above is handledEventsToo which ensures that this handler will be invoked no matter if it is already marked as Handled (which ListBoxItem does in ListBox).
See Marking Routed Events as Handled, and Class Handling for explanation.
See How to Attach to MouseDown Event on ListBox for example.
You can use Event="MouseLeftButtonUp"
Unlike "PreviewLeftButtonDown" it will get the ListBoxItem handled too.
You can use the SelectionChangedEventArgs argument of the SelectionChanged event to find what item is add or removed through AddedItems and RemovedItems, usually only have the latest clicked on, or if not, then look at the last item which is the count-1.

Resources