Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User Control in Stackpanel losing focus

I'm creating an XML Form Reader. Each of the control types are User Controls. However when the user taps somewhere on the form that isn't a focused control (i.e. TextBlock), the form jumps focus to the first focusable control in the page. (i.e. TextBox)

This scrolls the page to the top (usually), taking the user away from what they were just working on.

I have tried a lot of different things around the focus events but have hit a wall on how to solve this.

What would be the best way to handle this ? Any hints or tips would be greatly appreciated.

Thanks

EDIT (more info)

The "MASTER" page has a StackPanel

<StackPanel x:Name="pnlFormMain" ScrollViewer.BringIntoViewOnFocusChange="False"/>

For each control in the xml form, a UserControl is added to the stackpanel.

    <UserControl.Resources>
    <Storyboard x:Name="Show">
        <DoubleAnimation Duration="0:0:0.6" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="_WidgetMaster" d:IsOptimized="True"/>
    </Storyboard>
    <Storyboard x:Name="Hide">
        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="_WidgetMaster" d:IsOptimized="True"/>
    </Storyboard>
</UserControl.Resources>

<Grid x:Name="grdInput" ScrollViewer.BringIntoViewOnFocusChange="False">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="auto" />
        <RowDefinition Height="auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>


    <Grid Grid.Column="0" Grid.Row="0" ScrollViewer.BringIntoViewOnFocusChange="False">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="auto" />
        </Grid.ColumnDefinitions>
<!-- label -->
        <TextBlock x:Name="lblLabel" Text="Label" Grid.Column="0" VerticalAlignment="Center" Margin="3,6,5,5" TextWrapping="Wrap" />

        <!-- HINT -->
        <Ellipse x:Name="ellHint" Height="25" Width="25" Grid.Column="1" StrokeThickness="2" Stroke="LightBlue" Margin="5,0,5,0" Tapped="Hint_Tapped"  VerticalAlignment="Center">
            <Ellipse.Fill>
                <ImageBrush ImageSource="ms-appx:///XForms/Assets/information.png" />
            </Ellipse.Fill>
        </Ellipse>
    </Grid>
    <Frame x:Name="control" Grid.Column="1" Grid.Row="0" />
    <TextBlock x:Name="lblConstraintMessage" Grid.Row="2" Grid.ColumnSpan="99" FontSize="10" VerticalAlignment="Center" 
               HorizontalAlignment="Right" Margin="0,0,5,0" Visibility="Collapsed" />
</Grid>

The same UserControl is used for almost all controls. And the input for that control is a second UserControl that goes into the Frame near the bottom.

(e.g.)

<Grid x:Name="grdInput">        
    <TextBox x:Name="txtInput" Text="" Grid.Row="0" Grid.Column="1" Margin="15,0,0,0" LostFocus="txtInput_LostFocus" KeyDown="txtInput_KeyDown" TextAlignment="Right" />

    <Border x:Name="brdrValuePlaceholder" Background="Transparent" BorderThickness="0,0,0,1" BorderBrush="{ThemeResource TextControlBorderBrush}" HorizontalAlignment="Stretch" 
            Height="{ThemeResource TextControlThemeMinHeight}" Visibility="Collapsed">
        <TextBlock x:Name="lblInput" Text="" Grid.Row="0" Grid.Column="1" Margin="0,0,5,0" Tapped="lblInput_Tapped" TextAlignment="Right" HorizontalAlignment="Stretch"/>
    </Border>        
</Grid>

The LostFocus event there just sets a value in the database

Other controls on the master page is a Popup and a ProgressRing Along with a header bar.

EDIT 2

I have tried to do what I can with making the StackPanel unfocusable, and storing the previously focused control, but can get them to work as hoped.

I have put the source up on GitHub, I am new to GitHub, so if I need to do anything more, please let me know. The code is a bit older, but has the same problem. There is also a Android and iOS application in the solution, but only the UWP project has the issue.

The bounty is still alive, and will be awarded if anyone can help. Thanks

like image 435
Seige Avatar asked Apr 03 '18 22:04

Seige


2 Answers

Maybe it is focusing on the stackpanel itself?

Have dialog box popup or a textstring in the page itself to show what is always focused. That way you can see if the stacklayout is becoming focused.

Another possibility is that if you tap off, it is returning focus to the first element on the stacklayout (what it saw as tapped).

like image 198
Slipoch Avatar answered Nov 19 '22 18:11

Slipoch


It's not trivial to recreate your exact scenario. However, there should be several possible solutions to your problem.

The first thing that comes to my mind is to intercept the Preview*keyboard/mouse events within your form.

  • When a KeyDown/MouseDown/Tap outside your text box is detected while it has the focus, call update the binding expression of the FocusManager, and set Handled=true to prevent the KeyDown or MouseDown event from being processed further if a non-user control is clicked. A markup extension could be helpful too.
  • It might be also crucial to hangle PreviewLost*Focus to detect any unwanted focus changes.

Another approach could be to mark all no-user input UI elements as Focusable=false in the XAML, e.g.

<XY Focusable="False">
...
</XY>

or disable them all together.

like image 30
wp78de Avatar answered Nov 19 '22 19:11

wp78de