I have a WPF application that I am working on where there is a button that is obscured by a partially opaque rectangle overlay. The button is still visible, but it can not receive any events because they are all caught by the rectangle which is on top of it.
Is there any way to set a pass-through so that the event is received by the next visual item underneath? If not is there some other workaround that could be used in this situation?
Set IsHitTestVisible="false" on the opaque overlay.
You need to set IsHitTestVisible="False" for the control over your button.
This example shows that a button is covered by a border, but the border doesn't get any event since because of the IsHitTestVisible="False" condition of border:
<Grid Background="Yellow">
<Button Click="Button_Click" Width="100" Height="25"/>
<Border Background="Cyan" Opacity="0.4" Width="200" Height="200" IsHitTestVisible="False" />
</Grid>
C# code,
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("iiiiiii");
}
You could add the your own event to the rectangle event (or in the click event of the rectangle it self) and check there if it's with in buttons area
Rectangle.Click += your_click_event;
private void your_click_event(object sender, RoutedEventArgs e)
{
//check if it's coordinates are within the underlining button.
//fire button click event
}
But it would be more convient to set
IsHitTestVisible="False"
Like mentioned in other posts. UIElement.IsHitTestVisible Property
I would recommend to look in to routed events in WPF. Routed events get routed based primarily on the visual tree. Routed events support a RoutingStrategy of Bubble, Tunnel, or Direct.
Understanding Routed Events and Commands In WPF
Related
I have WPF application in which there are some controls on a screen layer.
Navigating between the controls using TAB (keyboard) works appropriately, and I can see the image gets focus using SNOOP.
BUT - Clicking the image doesn't set the focus on it.
If it matters - I enter a function I need via both (click and enter) events handlers... Just the focus is not being recieved in the click case, that's the confusion I can't understand.
Have you considered using a templated Button to show your image? You get the focus-on-click behavior, but show an image:
<Button>
<Button.Template>
<ControlTemplate TargetType="Button">
<Image Source="http://placehold.it/300x500" Stretch="Fill" />
</ControlTemplate>
</Button.Template>
</Button>
An Image element doesn't get focused by default when you click on it. You could write some code that focuses it though. Just handle the MouseLeftButtonDown event:
private void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Image img = sender as Image;
img.Focusable = true;
img.Focus();
}
<Image Source="pic.png" MouseLeftButtonDown="img_MouseLeftButtonDown" />
I have created a button using XAML and have defined some simple properties for it.
<Button Name="btnNext" Grid.Row="1" Content="PARA" Width="200" Grid.Column="1" Background="#FF2D2D2D" HorizontalAlignment="Right" FontSize="40" Height="380" BorderThickness="0" />
It happens that when I click on the button or put the mouse over, it changes color.
I have tried to escape this behaviour in the btnNext_Click method but it does not affect anything.
private void btnNext_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
button.Background = new SolidColorBrush(hexToColorConvertor("#FF2D2D2D"));
START_POINT += (uint)NUMBER_OF_BUTTONS1;
ReadFile(START_POINT);
}
}
Does anyone have any idea how to resolve this?
In XAML, button have default style for different states like Normal, MouseOver, Pressed etc..
Whenever button moves from one state to another, it changes its look using default style obviously. You can find more information related to default style here
Now, If you want to override this default behavior, you can do it easily with Expression-blend. More of this can be found here and here
Hope this information will help you.. :)
I have a UserControl which contains a Label and a TextBox. Both are placed inside a stackpanel which is placed in a border.
I now want to receive an Event when the mouse clicks somewere inside the stackpanel or the border. I tried several things, as using transparent Backgrounds, different Events like ismousedirectlyover etc.
Is there a way i can solve this?
You can try by capturing the mousedown event inside your textbox, your label and your stackpanel and bind them all directly to the same method, you will allways get the mousedown event independent on where you clicked.
You can also try to set the
Panel.Zindex
property to a higher number in the stackpanel and then only capture the mousedown event on it.
1) Add an handler for the MouseLeftButtonDown to the border:
<Border MouseLeftButtonDown="Border_MouseLeftButtonDown">
<StackPanel Background="Transparent">
<TextBox x:Name="Text" />
</StackPanel>
</Border>
2) Set the focus manually to the TextBox:
private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Text.Focus();
}
make sure to set the background of the stackpanel to transparent.
I'm developing a windows phone 8 XAML application.
I defined MouseEnter events for several objects in a XAML page. (For example two rectangles). After triggering the MouseEnter events of those objects, I press a button on the same page. Button press does not only trigger click event of it self. It also triggers MouseEnter event of the last Rectangle entered.
The problem can be reproduced with a new project with just two Rectangles and one Button. This behaviour does not appear always, but can be observed after triggering MouseEnter event of the Rectangles a few times.
My XAML objects are as follows.
<Rectangle Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100"
Margin="102,306,0,0" Stroke="Black"
VerticalAlignment="Top" Width="100"
MouseEnter="Rectangle_MouseEnter"/>
<Rectangle Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100"
Margin="314,306,0,0" Stroke="Black"
VerticalAlignment="Top" Width="100"
MouseEnter="Rectangle_MouseEnter"/>
<Button Content="Button" HorizontalAlignment="Left"
Margin="256,481,0,0" VerticalAlignment="Top" Click="Button_Click"/>
And code behind looks like this.
private void Rectangle_MouseEnter(object sender,
System.Windows.Input.MouseEventArgs e)
{
Debug.WriteLine("Rectangle_MouseEnter");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Button_Click");
}
If I remember, in Windows pone and Windows 8 apps it's better to use the tapped event instead of mouse events. It could be the problema. Take a look on this link:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.uielement.tapped.aspx
I understand how bubbling and tunneling works. However, i'm confused about using them.
Here is why:
I want to handle a mouse click event. To bubble it, there is MouseDown and, to tunnel it, there is PreviewMouseDown. However, MouseDown doesn't necessarily mean the user clicked the control. May be the user pressed the button and moved away from it to cancel the click.
I wouldn't want to change anything if the button is not being clicked.
So my question is, how are the Bubbling/Tunneling strategies useful?
If the event is listed RoutedEventArgs, then it's routed event. Routed events support a RoutingStrategy of Bubble, Tunnel, or Direct. Let's take a look at the event handler of Button.Click:
private void Grid_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button Test clicked!");
}
There specified RoutedEventArgs, so it's routed event. Because the preview were not specified in the name, therefore this Bubble event. This can be demonstrated in the following way:
<Grid ButtonBase.Click="Grid_Click">
<Button Name="TestButton" Width="100" Height="30" Content="Test" />
</Grid>
When you click on the TestButton, the event is to rise above the Grid, and displays a message:
Button Test clicked!
Usefulness of Bubbling/Tunneling strategies
Tunneling
Many of the standard controls listen to events, such as KeyDown, MouseDown, etc. For example -DataGrid control. I want by pressing the enter key the function was called adding a record. But DataGrid already has KeyDown event, so the event is not raised. So you have to do your logic in the Tunnel event - PreviewKeyDown, it will work before the KeyDown event. The same applies to RichTextBoxControl.
Bubbling
Sometimes, you need a global handler for a specific event, so it worked for all controls in VisualTree. Naturally, the a direct event you can not do it. Hence on the stage comes Bubbling event.
Another reason is the ideology of the WPF. This Button can contain anything: Image, another Button, etc:
The user can click on the TextBlock/Image in the Button. How do we know that the click was in Button? That's right, with the help of Bubbling event.
For more information, please see:
Understanding Routed Events and Commands In WPF
Edit
I changed little bit a Click handler:
private void Grid_Click(object sender, RoutedEventArgs e)
{
String message = "#" + eventCounter.ToString() + ":\r\n" +
" Sender: " + sender.ToString() + ":\r\n" +
" Source: " + e.Source + ":\r\n" +
" Original Source: " + e.OriginalSource;
lstEvents.Items.Add(message);
}
Result of click on the Button:
Hi though you can get some good articles regading this on net but still I will try to answer this.
Suppose you give a button a very plain appearance consisting of a single Rectangle, and provide a simple piece of text as the content Even with such basic visuals, there are still two elements present: the text and the rectangle.The button should respond to a mouse click whether the mouse is over the text or the rectangle. In the standard .NET event handling model, this would mean registering a MouseLeftButtonUp event handler for both elements.
This problem would get much worse when taking advantage of WPF’s content
model. A Button is not restricted to having plain text as a caption—it can contain any
object as content. The xaml below is not especially ambitious, but even
this has six visible elements: the yellow outlined circle, the two dots for the eyes, the
curve for the mouth, the text, and the button background itself. Attaching event
handlers for every single element would be tedious and inefficient. To work MouseDown We would have to add 8 MouseDownEvents to this bit of code.
<Button PreviewMouseDown="PreviewMouseDownButton" MouseDown="MouseDownButton">
<Grid PreviewMouseDown="PreviewMouseDownGrid" MouseDown="MouseDownGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas PreviewMouseDown="PreviewMouseDownCanvas" MouseDown="MouseDownCanvas" Width="20" Height="18" VerticalAlignment="Center">
<Ellipse PreviewMouseDown="PreviewMouseDownEllipse" MouseDown="MouseDownEllipse" x:Name="myEllipse" Canvas.Left="1" Canvas.Top="1" Width="16" Height="16" Fill="Yellow" Stroke="Black" />
<Ellipse Canvas.Left="4.5" Canvas.Top="5" Width="2.5" MouseDown="MouseDownEllipse" Height="3" Fill="Black" />
<Ellipse Canvas.Left="11" Canvas.Top="5" Width="2.5" MouseDown="MouseDownEllipse" Height="3" Fill="Black" />
<Path Data="M 5,10 A 3,3 0 0 0 13,10" Stroke="Black" MouseDown="Path_MouseDown_1"/>
</Canvas>
<TextBlock Grid.Column="1" MouseDown="TextBlock_MouseDown_1">Click!</TextBlock>
</Grid>
</Button>
WPF uses RoutedEvents Bubble/Tunnel /Normal, which are rather more thorough than normal events. Instead
of just calling handlers attached to the element that raised the event, WPF walks the
tree of user interface elements, calling all handlers for the routed event attached to
any node from the originating element right up to the root of the user interface tree.
As you said you know the concept of bubbling/tunneling so not going into that. But this is what these events are intended for i.e they let you know if the Mouse button was Down or Up on the control or its children.Events are working fine.For your scenario you should use the Click event of your button which tell if the mouse was down and up on the button itself.
Thanks