I Have created a Grid (g1) with a TabControl (t1). t1's TabItem content has Grid (g2). g2 has another TabControl as t20,t21,t22 (vertical TabControl) and each t2 series TabItem has another Grid (g3) .
The issue I'm having is that a mouse event is not working g3. The same function works when placed in g2.
I have tried placing a button instead of g3 and click event works, and if I add a button to g3, then the button click events work.
What could be causing the mouse event to not work?
You have not given any code, however, there is a very common 'gotcha' in Silverlight regarding mouse events. An element will not raise these events unless it has a background explicitly set. Set your Grid.Background to Transparent and hopefully your events will work.
(If that doesn't work, my net guess is Z-Index!)
Related
The title says it all: "How do I prevent TextBox or RichEditBox from losing focus after clicking on a disabled button?"
I tried setting AllowFocusOnInteraction to false, but that only works when the button is enabled. That property works well if, say, I have a button for setting text to bold or italic. The editor will not lose focus and everything works superb. But if I were to disable that button and then click on it, the editor loses focus. This causes several new issues for me. Would love some help with this. Thanks.
Also note that I have a UWP app. Not sure if it matters, though.
Okay, so I figured out the CORRECT way to fix the issue.
So the bold, italic, and underline format buttons are all within my custom toolbar. What I had to remember is that most xaml elements can be clicked on and therefore trigger a PointerPressed event so long as the element (a Grid element for example) has a background for the click to intercept. If the background is transparent the PointerPressed event will not fire.
Sooo, I made sure my toolbar had a solid background set and then I set a PointerPressed event on it. So whenever you click on the toolbar that event will fire and I simply set the e.Handled property to true;
So now because the button within the toolbar is disabled the pointer click will go to the next clickable element within the visual tree that is underneath the button that you clicked, which is my toolbar (which now has a background). When the toolbar is reached, the e.Handled event being set to true within the event handler will tell the system to do nothing further and so the RichEditBox retains its focus.
I know my writing here is very sloppy but I am sort of in a rush right now and so I will most likely come back and clean my answer up. Hope this helps someone.
wrap the disabled button in a Border or a Grid.
<Grid Tapped="DisabledButtonTapped">
<Button IsEnabled="false"/>
</Grid>
now with help of tapped method on this grid you can set focus back to your RichEditBox.
private void DisabledButtonTapped(object sender, object args)
{
MyRichEditBox.Focus(FocusState.Programmatic);.//use the x:Name of your richeditbox in place of "MyRichEditBox".
}
I have a little problem with winforms and mousewheel events.
I have a custom user control representing a slider. Now, I have a couple groups of sliders in which each group is wrapped inside a panel. All the groups are then wrapped in another panel (which has AutoScroll set to true) and this is wrapped in a form. The slider logic is implemented such that the mousewheel can be used to change its value. For this, the slider user control gets focus when the mouse is over the slider. However, when I scroll, also the AutoScroll parent panel scrolls with it.
I've already lost a lot of time on this issue. Anybody knows what is happening here and how I can solve it? I thought the event was bubbling to the parent panel but I don't find a Handled property on the event when handling it in the Slider control (as is possible with WPF).
many thanks
We implemented the Slider as a complete custom user control (inheriting the UserControl class) with own look-and-feel.
You might have noticed that a UserControl doesn't show the MouseWheel event in the Properties window. Hint of trouble there. The WM_MOUSEWHEEL message bubbles. If the control that has the focus doesn't handle it then Windows passes it on to its Parent. Repeatedly, until it finds a parent window that wants to handle it. The Panel in your case.
You'll need to invoke a bit of black magic in your slider control. The actual event args object that get passed to the MouseWheel event is not of the MouseEventArgs type as the event signature suggests, it is HandledMouseEventArgs. Which lets you stop the bubbling. Like this:
protected override void OnMouseWheel(MouseEventArgs e) {
base.OnMouseWheel(e);
// do the slider scrolling
//..
((HandledMouseEventArgs)e).Handled = true;
}
If you are creating event dynamically like
object.event += new EventHandler<EventArgs>(eventfunction);
try un-registering the event after the eventfunction is called like this
object.event -= new EventHandler<EventArgs>(eventfunction);
Here's how my element tree is composed (irrelevant informations removed).
<TabItem Style="Click_PutNormalCursorBack">
<ScrollViewer>
<ItemsControl Style="ContainsMuchLabels_n_CollapsibleGroupeHeaders">
<Label Style="Click_ChangeCursor" />
</ItemsControl>
<ScrollViewer>
</TabItem>
I am simulating Drag n Drop. When you click on the clickable label, it transform's your cursor to guive you the impression your dragging it. What i want is that clicking on the TabItem, it put back your normal cursor.
I cant use PreviewMouseDown event because it would never allow the label to be clicked.
One solution i found was adding a big panel to my element tree between my ScrollViewer and my ItemsControl with a transparent background to recieve clicks, putting an event handler on my ItemsControl's CollapsibleGroupHeader and ItemsPanel but its not really an elegant solution.
I tough RoutedEvents in WPF where ther to resolve that kind of problems...
Note : my handlers are not my my styles, styles where just ther for guiving more information
Is ther a better solution than mine?
Use the MouseDown event for both. Just don't mark the event handled (e.Handled = true) if the event doesn't apply. For example, in your clickable tab, if it's clicked when the cursor isn't in the drag state, don't mark handled. Once the cursor IS in the drag state, if the user clicks again on the clickable label, don't mark handled (unless you want that event to reset the cursor). You could also use the PreviewMouseDown event on the tab, but again don't mark handled unless that click is from a cursor that originates from the label.
If you don't mark an event handled it continues to propagate so multiple controls can handle it. Even if something does mark an event handled and you still want to handle it, you can make an event fire even when marked handled: see "Adding Instance Handlers That Are Raised Even When Events Are Marked Handled" in this article
Let's say I have a created a Form class and a CustomControl class.
On my Form I have two instances of the CustomControl, and a Panel.
Panel has 4 event handlers: MouseEnter (to give a different cursor), MouseLeave (to reset the cursor), MouseDown (to start the dragging thread), and MouseUp (to kill the dragging thread and do post-drag logic).
I can drag the Panel onto the CustomControl. When I do this, the code in Form detects what I have done and deletes Panel from Form.Controls, passes some meta-information to CustomControl, which then creates a Panel on itself.
Basically, it is a hand-over. The Panel object now belongs to the CustomControl.
(This is necessary. It's complicated to explain why, but imagine the custom control has something like scrollbars, and it's necessary for the Panel to belong to the CustomControl so that it will scroll with the CustomControl.)
Now, when I click down on the Panel in the CustomControl, the Panel's MouseDown is triggered, it gets deleted from CustomControl.Controls and sends some meta-information back to the Parent (the Form), which then re-creates the Panel as it was at the start - however already in a dragging state so that the user can re-position the Panel onto the second CustomControl, or perhaps put it back onto the Form. The function which creates the Panel when the Form is first initialised is exactly the same function which creates it now.
However, the Panel's MouseDown has not been triggered. The mouse is down, but the event is not firing because the mouse was already down when it was created. So, I manually call the MouseDown handler in the function in Form which accepts the meta-information from CustomControl.
Unfortunately, this only half-works. The MouseUp handler isn't firing. I can pick up the Panel off the CustomControl and drag it around on the Form as expected, but when I release the mouse, the Panel is stuck to the cursor.
I'm not really sure how to get around this?
An ideal solution would be for, when the meta-information is passed back to Form and the new Panel is created, the MouseDown event to somehow fire naturally as though the user had just clicked down on the Panel.
It sounds like you are creating a new instance of Panel when you move it from CustomControl to Form and back and loosing it's state.
You should either try to pass the actual instance owned by Form to CustomControl without creating a new one or you could capture the state of the Panel in another object which you can pass to the constructor when you create a new Panel so that it is in the same state as the one you were dragging?
It seems as though you are trying to manually fire mouse events to compensate for problems in your design.
Always better to give some example code if you can than lengthy textual explanations.
Look at this
Instant of custom control is disappear when click outside it
I have problem like you.
you shouldn't use a local variable for handling mouseEvent.
Try to use "Capture" function. It's work for me.
I have a custom UserControl. I want to use it in a few different products, so I want something that can be implemented inside of the UserControl itself. I want to know when the user has clicked outside of the bounds of the UserControl so that I can hide it, similar to a ComboBox. How can I do that?
I tried handling the click event, but it only seems to fire if the click occured within the bounds of the control.
That's what the Capture property is designed to do. Set it to true and all mouse messages are routed to your control, even if it moves out of the window bounds. Check the e.Location property in the MouseDown event.
Hm, you may be able to accomplish what you want by listening to the GotFocus/LostFocus events. ComboBoxes give the drop downs focus when they open and close them when they lose focus.
do this
Select all controls on your form including form
In Property Window select MouseClick event
Now enter below Code in Common_MouseClick
Code:
if (!sender.Equals(yourControl))
{
yourControl.Visible=false;
}