Detect focus lost from a WPF control group

I am creating a GUI using code that has editable content. When the user clicks on the static display, the control is replaced with the one that allows editing. In some cases, the display control (for example, Label ) is replaced by a group of controls, such as ComboBox and TextBox .

I want to determine when the focus is lost from my group of editable controls in order to switch the interface back from the editor to the display view for this element.

For example, I might have a GUI in a tree, such as Panel1(Panel2(Button1, Button2), Button3) , and I would like to detect when focus is lost from Panel2 . I tried the following (F # code):

 open System.Windows let button1 = Controls.Button(Content="1") let button2 = Controls.Button(Content="2") let button3 = Controls.Button(Content="3") [<System.STAThreadAttribute>] do let panel1 = Controls.StackPanel() let panel2 = Controls.StackPanel() panel2.Children.Add button1 |> ignore panel2.Children.Add button2 |> ignore panel1.Children.Add panel2 |> ignore panel1.Children.Add button3 |> ignore panel2.LostFocus.Add(fun _ -> printfn "Panel2 lost focus") Application().Run(Window(Content=panel1)) |> ignore 

The panel2.LostFocus event is panel2.LostFocus when panel2.LostFocus is pressed after button2 pressed, as expected, because the focus moves from panel1 to button3 . However, it also fires when button2 pressed after button1 pressed, although Panel2 never lost focus.

Reading the MSDN documentation on focus in WPF I tried adding:

 Input.FocusManager.SetIsFocusScope(panel2, true) 

but it actually made the problem worse! Now the panel2.LostFocus event is panel2.LostFocus only when the focus shifts from one child of Panel2 to another, and not when Panel2 actually loses focus.

How do I get the desired effect?

+6
source share
1 answer

Thanks to Ian Voyce on Twitter I was able to get the features I need using the IsKeyboardFocusWithinChanged event. Here is a demo:

 open System.Windows let Button x = Controls.Button(Content=x, Width=64.0, Margin=Thickness 3.0) let Panel ctrls = let panel = Controls.StackPanel() for ctrl in ctrls do panel.Children.Add ctrl |> ignore panel let label = Controls.Label(Content="Edit 12") let button1 = Button "1" let button2 = Button "2" let button3 = Button "3" let panel = Panel[button1; button2] [<System.STAThreadAttribute>] do label.HorizontalContentAlignment <- HorizontalAlignment.Center label.MouseLeftButtonDown.Add(fun _ -> label.Content <- panel) panel.IsKeyboardFocusWithinChanged.Add(fun e -> if not(unbox e.NewValue) then label.Content <- "Edit 12") Application().Run(Window(Content=Panel[label :> UIElement; button3 :> UIElement])) |> ignore 
+6
source

All Articles