2

I'm building a window for a kiosk application that has an admin screen to connect to a wifi network. Actually, I'm porting an existing WinForms app that already does this, but doesn't give us the flexibility we want to create a more interesting UI. So, we're moving to WPF.

The window is pretty straightforward, it has a listview to show networks that it finds, and if you click on one, it will connect to it. In order to connect, we need to prompt for the security code for that network if it needs one. To do this, we open a popup that has three sections - a "dialog-y" prompt section at the top, a spacer row, and a blank border that will sit behind an onscreen keyboard, but have nice rounded corners.

That top section has a header, a text box, and two buttons, connect and cancel. Again, nothing complex.

All this works. You click a network, we show the popup and the keyboard, except: the textbox for the passcode never gets the focus. Even if you click on it. No focus. The only trick I've found to get it to focus is to click off the popup (like back on the listview, which is already ignoring clicks if the popup is open, so it's safe), then click back on the textbox, and voila! focus. I really don't think I want to put that in a user manual though.

Here's the popup portion of the xaml:

<Popup x:Name="popPasscode" Placement="Top" HorizontalOffset="50" VerticalOffset="1000" AllowsTransparency="True" >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="50" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Border Grid.Row="0"  Background="White" CornerRadius="20" Width="600" Height="400">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Border Grid.Row="0" Background="#464646" Height="50" Margin="8,10,8,0" CornerRadius="25" >
                    <Label x:Name="lblTitleSecurityCode" Content="Enter the security code" Foreground="White" FontFamily="Arial" FontSize="30" FontWeight="Bold" HorizontalAlignment="Center"/>
                </Border>
                <TextBox Grid.Row="1" x:Name="tbPasscode" Height="50" FontFamily="Arial" FontSize="30" Margin="40,0,40,0"/>
                <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="10,0,10,10" HorizontalAlignment="Center">
                    <Controls:ImageButton x:Name="btnCodeConnect" Content="Connect" Height="70" Width="275" Foreground="Black" Style="{DynamicResource PlainButton}" FontFamily="Arial" FontSize="30" FontWeight="Bold" Click="btnCodeConnect_Click"  HorizontalAlignment="Center" VerticalAlignment="Center"  />
                    <Controls:ImageButton  x:Name="btnCodeCancel" Content="Cancel" Height="70"  Width="275" Foreground="Black" Style="{DynamicResource PlainButton}" FontFamily="Arial" FontSize="30" FontWeight="Bold" Click="btnCodeCancel_Click"  HorizontalAlignment="Center" VerticalAlignment="Center"  />
                </StackPanel>
            </Grid>
        </Border>
        <Border Grid.Row="2" x:Name="brdrKbd" Background="White" CornerRadius="20" Width="1200" Height="420"/>
    </Grid>
</Popup>

Here's what I'm currently trying to do during the listview click event to get focus to the control. Note that I tried to fake the "set focus to the listview, then set it to the textbox, but that didn't work.

// set the popup location and width and keyboard border width based on the current screen width
popPasscode.IsOpen = true;
// open the on-screen keyboard - synchronous call, doesn't return until it's open and idle
FocusManager.SetFocusedElement(this, lvAvailNetworks);
tbPasscode.Focusable = true;
FocusManager.SetFocusedElement(popPasscode, tbPasscode);

I've tried a couple different things for the DependencyElement for tbPasscode, but I really have no idea what I'm doing, or that what I'm doing is making any difference. Oh, did I mention I just finished my first week of WPF coding? Yup, WPF newbie alert.

I saw this post, but it didn't help much, since I thought I was already doing all that.

Community
  • 1
  • 1
gbryant
  • 751
  • 5
  • 19
  • can you share the code how you are opening the popup? – Nitin Oct 22 '13 at 03:20
  • It's there in the first line of the second code section which is from the Click event handler for the listview, I set IsOpen to true for the popup. – gbryant Oct 22 '13 at 10:55
  • Sleep is such a wonderful thing. The onscreen keyboard is an older c++ app that opens with NOACTIVATE settings. What if that's the problem? So I tried just not opening the keyboard, and I was able to click on the textbox and give it focus without having to click the background. Initial problem solved by adding a call to Activate() after opening the osk - apparently you can set focus all you want, but it won't activate, contrary to my expectations at least. Now, it still doesn't set focus where I want it to ... – gbryant Oct 22 '13 at 11:00

1 Answers1

1

Instead of MouseDown, register to MouseUp event on ListView/ListViewItem. In the handler you can do

     popPasscode.IsOpen = true;
     Keyboard.Focus(tbPasscode);

The MouseUp on your ListView takes focus away from the Popup, so open your Popup in MouseUp instead of MouseDown

Nitin
  • 18,344
  • 2
  • 36
  • 53
  • I wasn't using mousedown, I was using onselection changed, but apparently that happens during the mousedown. I swapped for the mouseup, used the code found here (http://stackoverflow.com/questions/929179/get-the-item-doubleclick-event-of-listview) to get the row, and it worked. Thanks! – gbryant Oct 22 '13 at 12:00
  • Oh, and after more reading, I replaced all the FocusManager garbage with a simple Keyboard.Focus(tbPasscode); Much more maintainable. – gbryant Oct 22 '13 at 12:04