Try to catch mouse event in HierarchicalDataTemplate - wpf

I'm fairly new to wpf and this website. Please give me some mercy if I show some mistakes.
My HierarchicalDataTemplate ,which is my treeview item, consists of multiple components: two textblocks , image , and checkbox with some stack panels for the layout. My MouseEventHandler, which is to catch when user click on textboxes, image , or checkbox , is TreeViewItem.Selected. But when I click on the tiny space between those components, it doesn't trigger TreeViewItem.Selected.
My first initial thought was that I might need to specify event handler on the stack panel which was for the layout of my HierarchicalDataTemplate . However, it didn't rise the event ,even though I made event handler on stack panel specifically.
Could you give me some guidance?
ps. I used binding for IsSelected property but it never notified to change its property

Set Background="Transparent" for topmost layout container inside your HierarchicalDataTemplate.
The following Grid doesn't raise MouseLeftButtonDown event:
<Grid MouseLeftButtonDown="handler" Width="200" Height="200">
</Grid>
But the following does:
<Grid MouseLeftButtonDown="handler" Width="200" Height="200" Background="Transparent">
</Grid>
This is because in the 1st case it doesn't have background and there's nothing to raise MouseLeftButtonDown event. So the event will be raised only if user clicks on some element inside that Grid.

Related

WPF, what kind of controls will handle MouseLeftButtonDown event?

I have a DataGridControl,and its cell's DataTemplate overwritten to TextBoxs,by clicking outside the cells but still on the DataGrid, I want the TextBox to lose Keyboard focus so that it can Commit the change, but it seems the DataGrid won't handle the MouseLeftButtonDown event, so I have to manually add a handler to the Grid,and in the handler:
e.Handled = true;
Keyboard.Focus( sender as UIElement );
to make the parent panel "focusable".
By using Snoop, I notice that controls like TextBox, Button are capable of handle MosueLeftButtonDown event, while Panels are not,event if set "Focusable" property to "True". Does anyone know the reason behind this, Thanks.
To simplify the situation: suppose we have a TextBox and a Button on a Grid:
<Grid Background="AliceBlue">
<TextBox Height="25" Margin="50" Text="abcd"/>
<Button Height="25" Margin="50,100,50,0"></Button>
</Grid>
when I click on the TextBox, it gets KeyBoard focus, when I click the blank area of the Grid, I want the TextBox to lose focus, the problem is Grid is not focusable compared with TextBoxes and Buttons.
The documentation for Panel shows that Panel can handle mouse events:
https://msdn.microsoft.com/en-us/library/system.windows.controls.panel_events(v=vs.110).aspx

Catching right mouse click on user control level

<UserControl>
<Grid>
<!-- multiple controls here -->
</Grid>
</UserControl>
As the above example says, there are multiple MS / 3rd party controls hosted on UserControl. I need to catch mouse right click over the UserControl (or any of its child controls). It seems that PreviewMouseRightButtonUp event is not fired when clicked on some of the 3rd party controls inside the UserControl. As per documentation, PreviewMouseRightButtonUp is not a tunneling event, but a direct event, so it is possible that some 3d party controls do not notify the subscribers about this event.
I have also tried to add handler to this event, but still no result
AddHandler(UserControl.PreviewMouseRightButtonDownEvent, new RoutedEventHandler(GetHandledToo), true);
AddHandler(UserControl.PreviewMouseRightButtonUpEvent, new RoutedEventHandler(GetHandledToo), true);
AddHandler(UserControl.MouseRightButtonDownEvent, new RoutedEventHandler(GetHandledToo), true);
AddHandler(UserControl.MouseRightButtonUpEvent, new RoutedEventHandler(GetHandledToo), true);
So, is there a way to always catch the right mouse button event on the user control level, no matter if it is being marked as handled or not?
Edit: I have found where the problem lies. The problem lies in the ContentControl which has not yet evaluated its content. Example:
<ContentControl x:Name="chart" Content="{Binding DiagramScreen}" />
ContentControl recolves its structure through DataTemplate. If DiagramScreen is NULL, the ContentControl's content is not yet created. This means that the space that this ContentControl occupies in UserControl is not responding to Mouse events. How Can I make ContentControl respond to mouse events, even if its content is NULL?
I think if it is handled you can't get it further for bubbling event. A workaround is to pass your host object to your user control. After that, you can call whatever method you want from your host object. It's ugly but I think it will work

Problems with using Controls.Popup as error adorner in WPF

My (simplified) validation template is
<Grid>
<Border x:Name="ErrorAdorner"
BorderBrush="Red">
<AdornedElementPalceHolder />
</Border>
<Popup x:Name="ErrorPopup"
PalcementTarget="{Binding ElementName=ErrorAdorner}"
Placement="Bottom"
StaysOpen="false"
IsOpen="true">
<Grid>
<TextBloxk Text="Error!!!" />
</Grid>
</Popup>
</Grid>
The adorned element is typically a textbox
The problem I have with this approach is that, as soon as I click inside the textbox, the ErrorPopup disappears and the ErrorAdorner remains visible. Desired behavior is that both should stay visible.
Things tried:
Set StaysOpen to true on ErrorPopup. Problem: when you resize/move the parent window when the error is visible, the ErrorPopup remains at the same location, it doesnt move along with the textbox
Use a StackPanel around the textbox (adorned element) and the error message text block. Problem: Popup comes with positioning capabilities ie., if there is not enough screen area below the textbox for the adorner, it automatically relocates it. But if a stack panel is used, error message just cuts off if there is no space or it changes the textbox layout(not desired)
So in essence, I want to use the popup for its positional capabilities, but somehow want to fix the visibility problem
The problem here is that you can resize the window even if the cursor is inside the TextBox, you cannot get any useful state information out of that, so if you make the IsOpen dependent on that you still get dislocated popups.
Possibly this related question can help you with the placement.

Silverlight ListBox: How to find out if user is currently dragging the scrollbar slider?

Scenario: I have a ListBox, containing a WrapPanel from the Silverlight Toolkit as ItemsPanel:
<ListBox x:Name="listBoxFaelle">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<Grid>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListBox.Template>
</ListBox>
This ListBox gets populated automatically with the results of a RIA service call every 60 seconds. While the application is waiting for the LoadOperation to complete, it displays the standard BusyIndicator that is part of the Silverlight Business Application template.
This works fine as long as the user is not dragging the scrollbar slider of the ListBox when the Timer Event fires.
Problem: If the user is dragging the scrollbar slider when the BusyIndicator is being displayed, the scrollbar doesn’t work anymore, afterwards. It looks like the mouse pointer remains captured to the slider even if the left mouse button is released. I assume this happens because the BusyIndicator temporarily takes away the focus from the slider while it is being dragged.
Question: Is there a way to find out if the scrollbar slider of the ListBox is currently being pushed?
As far as I know there is no status/property to find out if the slider is being pushed.
That said you could try to keep track of it yourself by handling MouseLeftButtonDown and Up events but you might have to consider other events as well depending on your scenario (mouse wheel?)
MouseLeftButtonUp Occurs when the left mouse button is released (or the tip of the stylus is removed from the tablet) while the mouse (or the stylus) is over a UIElement (or while a UIElement holds mouse capture). (Inherited from UIElement.)
It might also be possible to solve this the other way around by releasing the MouseCapture (if that is causing the problem) by using ReleaseMouseCapture
Again, it depends on what you want to happen from the user's point of view: skip the loading of the data (this is what I would prefer because I do not like the content to be changing when I am scrolling) or reset the listbox and scroll to the top (ugly in my opinion)

WPF Combo box + MouseLeftButtonDown

Hopefully someone can help because I haven't been able to figure this out. Here's my xaml code for the popup/combo box, please not there is other code before and after this for the rest of the layout.
<Popup x:Name="popupMethods" Height="400" Width="150"
StaysOpen="False" Placement="Bottom" IsOpen="false"
HorizontalAlignment="Left">
<ComboBox x:Name="combo" MouseLeftButtonDown="combo_MouseDown">
<TextBlock>Hello</TextBlock>
<TextBlock>World</TextBlock>
<TextBlock>This</TextBlock>
<TextBlock>is</TextBlock>
<TextBlock>Autocomplete</TextBlock>
<TextBlock>Textbox</TextBlock>
</ComboBox>
</Popup>
Have it set up to popup on the screen whenever the user starts typing, which works. The problem is I want the user to be able to click one of the words in the combo box and that gets inserted into the text box. This parts not working as the MouseLeftButtonDown is never being fired. I've tried a couple of different methods including the one from this site
http://www.designerwpf.com/2008/12/03/getting-a-mouseleftbuttondown-or-mouseleftbuttonup-
event-from-your-textbox/
as well as one I saw somewhere else that was combo.MouseLeftButtonDown += delegate { };
Thanks for any help.
Instead of MouseLeftButtonDown event handler, use PreviewMouseLeftButtonDown you can achieve the same.
You probably want to look at the SelectionChanged event. It fires whenever an item in the ComboBox's drop down is selected.
I think that the ComboBox internally handles the MouseLeftButtonDown event, and that is causing it not to be passed on to your code.

Resources