How to get control with lower zindex when mouse clicked in wpf? - c#

I've several controls in the same canvas and may one be covered by another. They are all with same zIndex, but for the order loaded, some being up and others down.
My Question if Acontrol is over Bcontrol, and I click on them, but only A gets the click event. How can I make B get the event, too? Thanks.

If you only wanted the one in the back to get the event, then for all the controls in front of the first one, you have to set IsHitTestVisible = False for the one behind to get the event - but this isn't what you want.
If you want them all to get the event think of the entire UI as a tree of elements. All of these controls you're talking about are siblings. When something is clicked, the parent is the first to get notified, and if it doesn't handle the click, it gets passed down to the visible child element of that parent at that mouse position, and so on until it's handled. Your only way to stop the child that gets clicked from handling the mouse click is to have the common parent of all the siblings handle the event first.
You will then have to do something clever in the parent's handler to invoke the click event of all child elements that can be found beneath the mouse - the problem is that whereas the framework used to do the hard work of determining which control was under the mouse, you will will now have to do that hard work.

No chance. Even if you mark MouseClick as unhandled it will route to parent element (Canvas) not sibling. The only way is hit-testing. When the user click on Acontrol you should hit-test to determine whether another control is under it.
You must use hit-test with callbacks. This one allows you to skip Acontrol in order to find Bcontrol. If you find it, you can treat Bcontrol as clicked.

Related

WinForms Button Click event and similar events depend on focus

I have the next situation:
there is a client app with a Form
the Form contains a few TabControl's
there are different controls on TabPage's of TabControl's
when the user clicks on any control, I need to activate the TabPage that is a parent of a control. For that I use a TabPage Enter event
when the TabPage gets activated, I need to make request to the server app, and I put focus to a hidden TextBox to disable UI
The problem is, when I click on a Button on another TabPage, in TabPage.Enter event handler I take focus to my hidden TextBox, and it seems like Button click event doesn't have enough time to be processed. When I put timer and handle TabPage.Enter event after 100 ms, the Button click event seems to be fired well. Same thing happens to all the controls: CheckBox doesn't get checked, RadioButton too. I wouldn't like to use timer, as that is not a stable solution.
Any ideas how could I make TabPage to process all mouse events before I take focus to hidden TextBox? I tried to use Application.DoEvents(), but that didn't help.
You are using a wrong event for a wrong control for what you are trying to do.
Enter event for TabPage is going to be fired when that page becomes an active control of the current form which might not happen under certain conditions. Instead, you need to use Selecting or Selected event of TabControl, depending on whether you want to cancel switching to a different tab or not (see TabControlCancelEventArgs parameter of Selecting event). In your case, Selecting event would be more appropriate since it won't allow switching to a selected tab until event is complete (unless you're doing an asynchronous request to the server). Additionally, you may no longer need to use the hidden TextBox.
UPDATE
Regarding comments to OP, when you have 2 (or more) TabControls on a form and you want to get notified when you press a button in any tab of a different TabControl, you can use Enter event for TabControl. Use a global variable to store which TabControl was activated in the Enter event and then send server request for a currently active tab of that activate TabControl.
If this doesn't work for your scenario, then you need to carefully examine your workflow and see if it can be improved in relation to what you want to accomplish.

What is the property that says a button was selected in c#?

i've been searching on internet for the property that says that a normal button was selected or not, i think there must be one because when you click a button, it turns light blue, regardless the mouse is over it or not, and when you click another button, the previous button changes back to normal and the new clicked button is set light blue.
I need it to know which button was just selected and draw a "resizing" square on it, and it gotta last as long as the button remains as the "selected one".
thanks in advance.
What you are looking for is the Focused property. For actually any Control it returns, whether it has input focus or not (so e.g. hitting Enter will cause the button to be clicked as well). Since it sounds like you want to be notified whenever that property changes, you should use the GotFocus and LostFocus events.
You can give a Control focus programmatically by calling Focus.
you can do two things,
you can do it with the events: mouseEnter and MouseLeave,
this events launches when the mouse enters or leaves the visible control area,
also the focused(boolean) property gets and sets the "selected" element
one solution could be to:
private void onElementMousenter(blablabla,sender e);
{
e.Focused=true;
}
and assign the mouseEnter events in all controls to this one so the last element will be the "selected one" until you select another

WPF: LostFocus as in Old WinForms

I am not getting it after quite a research, that how can I implement simple Lostfocus like we use to do in Winforms. In Windows Form Control, we usually have LostFocus which I use when someome press TAB to lose focus or use mouse to select other controls. But it is not the case with WPF. I first use LostFocus, but when i press tab it doesn't fire the event. however when I click using mouse to other control it does get fired properly. So, this doesn't solve my problem.
Second, I try to use LostKeyboardFocus, it does get fired when using TAB key, and on few occassion when I use mouse to select other element, but not when I select menu item from Parent window menu.
Also, I have my control on User Control, that I put in TAB control on parent window. But when I press TAb key it always select the Parent Window Menu instead of TreeView I have in UserControl.
Any suggest is great help. Thanks.
Well, my quest for finding logically reasoning is still not satisfied, but I get the simple thing done simply.
#Daniel, as I said I think the two questions are related, well the answer is indeed related. Maybe you can explain my finding that I am putting as answer here.
I simply set the TabIndex property of my Textbox and other control [TreeView] as 1 and 2, now when I press TAB or select the TreeView item using mouse, i got Lostfocus fired up. and since I have Tab Index set within control, it doesn't select Menu item of parent [it does select it as last now]. So that make Lostfocus the function I should use for my purpose.
Anyone with explanation or better solution is still requested to share it. Thanks.

How to prevent a gridview to get focus?

I have 2 grids. When user is doing edits in one grid, I want to disable the other grid from getting focus, or atleast other grid from changing its foccussed row.
Example:
Parent grid, children grid.
If user is making edit in children of particular parent. I want to prevent user from suddenly shifting focus to different parent row. how to do that ?
The only ways you can prevent a control receiving focus is to change it's Enabled or Visible properties.
Simply changing the parent's Enabled property to "false" (e.g. for the CellBeginEdit) and then back to "true" (e.g. in the CellEndEdit event) will prevent the user from selecting a new parent row.
There are a lot of ways to do this but thats how I would do it (just a concept so ignore if any property does not match):
Create a property called mode and then use enumeration to set it to Edit or None etc.
Suppose you have GridViewParent and GridViewChild. In the FocusedRow event of child grid, at the start of all code, set the value of mode to Edit and at the end of all code in the event set it to None.
Then in the FocusedRow event of parent grid check whether the mode value is edit or not, if it is edit then use e.Cancel or something to get out of the focused event of the parent.
Now if you let me know exactly which grid are you using I might send you the code.

Can I make this easier? Bubbling vs Tunneling in WPF?

I am working with drag and drop functionality in a WPF application.
I have a tree structure such as the following.
StackPanel
- Border 1
- Grid A
- Grid 1
- Grid 2
- Border 2
- Grid B
- Grid 1
- Grid 2
This is my attempt to show the tree representation of the UIElements in my WPF application.
so the stack panel contains Grids with nested grids within it. These are being defined dynamically in code, and not in XAML.
I have the inner Grids(1 & 2) handling Drag and Drop events. The problem I am having is that when a drop operation is being performed, and it is dropped on the border of one of the grids, it falls through and hits the StackPanel Drop. What I would like to do is when an item is dropped on the border, I would like it to fall through to the same drop event handler.
I am fairly new to the idea of Routed Events and Bubbling and Tunneling events. I am aware that I need this event to travel down the element hierarchy which makes me believe that I am in need for "Tunneling" Event. Does this mean that I am supposed to attach the border to an event handler. Right now I have the following code for the Grids to be subscribed to the event.
fieldItemGrid.PreviewDrop += Grid_Drop;
private void Grid_Drop(object sender,DragEventArgs e)
{
//React to Drop Event Here
}
Am I able to do something simpler then rewriting the code that goes here in a Border_Drop Event?
Thanks ahead of time.
I think it would be best to add a very tight (no padding) container (e.g., a Grid) around the area that should act as a dropzone. Then use the tight container to handle the drop.
this way it doesn't matter what borders are specified. Only a padding of the tight container or a margin on the child controls will then mess it up.
The way routing working the preview event starts at the top of the tree until it reaches the element that initiated the event and then the normal event starts at the element itself and works towards the top of the tree.
In your situation, if border is the drop target, the sequence goes this (if event goes unhandled):
PreviewDrop -> StackPanel
PreviewDrop -> Border
Drop -> Border
Drop -> StackPanel
so the event will never reach any of the inner grids when the drop occurs on an element outside the grids. In other words, it will never tunnel into any children of the drop target because the tunnel stops where the drop occurred. It makes sense, how would it know which child was the right child to tunnel into if there were more than one?
As a result, you have to install the drop event handler on the largest element that visually represents the conceptual drop target. You can either switch the order of "Border 1" and "Grid A" or move your drop event handler for "Grid A" to "Border 1".

Categories

Resources