简体   繁体   English

Stackpanel中的用户控件失去焦点

[英]User Control in Stackpanel losing focus

I'm creating an XML Form Reader. 我正在创建一个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 (ie TextBlock), the form jumps focus to the first focusable control in the page. 但是,当用户点击不是聚焦控件(即TextBlock)的表单上的某个位置时,表单会将焦点跳转到页面中的第一个可聚焦控件。 (ie TextBox) (即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 “MASTER”页面有一个StackPanel

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

For each control in the xml form, a UserControl is added to the stackpanel. 对于xml表单中的每个控件,UserControl将添加到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. 几乎所有控件都使用相同的UserControl And the input for that control is a second UserControl that goes into the Frame near the bottom. 并且该控件的输入是第二个UserControl ,它进入底部附近的Frame

(eg) (例如)

<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 LostFocus事件只是在数据库中设置一个值

Other controls on the master page is a Popup and a ProgressRing Along with a header bar. 母版页上的其他控件是PopupProgressRing以及标题栏。

EDIT 2 编辑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. 我试图尽我所能使StackPanel不可聚焦,并存储以前专注的控件,但可以让它们按照希望工作。

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. 我把源代码放在GitHub上 ,我是GitHub的新手,所以如果我需要做更多的事情,请告诉我。 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. 解决方案中还有一个Android和iOS应用程序,但只有UWP项目存在问题。

The bounty is still alive, and will be awarded if anyone can help. 赏金仍然存在,如果有人可以提供帮助,将会获得奖励。 Thanks 谢谢

Maybe it is focusing on the stackpanel itself? 也许它专注于stackpanel本身?

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. 这样你就可以看到stacklayout是否正在变得更加集中。

Another possibility is that if you tap off, it is returning focus to the first element on the stacklayout (what it saw as tapped). 另一种可能性是,如果你点击它,它会将焦点返回到stacklayout上的第一个元素(它看到被点击的东西)。

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. 我想到的第一件事是截取表单中的Preview *键盘/鼠标事件。

  • 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. 当在具有焦点时检测到文本框外的KeyDown / MouseDown / Tap时,调用更新FocusManager的绑定表达式,并设置Handled=true以防止如果非用户控件进一步处理KeyDown或MouseDown事件点击。 A markup extension could be helpful too. 标记扩展也可能有用。
  • It might be also crucial to hangle PreviewLost*Focus to detect any unwanted focus changes. 挂起PreviewLost * Focus来检测任何不需要的焦点变化也是至关重要的。

Another approach could be to mark all no-user input UI elements as Focusable=false in the XAML, eg 另一种方法可以是在XAML中将所有无用户输入UI元素标记为Focusable=false ,例如

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

or disable them all together. 或者将它们全部disable

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM