【问题标题】:UWP Prevent Auto-Focus on AutosuggestBoxUWP 防止自动关注 AutosuggestBox
【发布时间】:2017-07-13 19:50:14
【问题描述】:

我在ContentDialog 中有一个AutosuggestBox,如下所示:

<ContentDialog x:Name="BrowseBySourceDialog"                                   
            Grid.Column="1"
            PrimaryButtonText="{x:Bind ViewModel._BTN_ok}"
            PrimaryButtonClick="BrowseBySourceDialog_PrimaryButtonClick"
            SecondaryButtonClick="Dialog_SecondaryButtonClick"
            SecondaryButtonText="{x:Bind ViewModel._BTN_close}"
            Opened="BrowseBySourceDialog_Opened"
            GotFocus="BrowseBySourceDialog_GotFocus"
            Style="{StaticResource ContentDialogStyles}">

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>


    <Border Background="#1A503E"
                MinHeight="40"
                Grid.Row="0">

        <TextBlock Text="{x:Bind ViewModel._HEADER_BROWSE_sourceOrganization}"                     
                    Style="{StaticResource DialogTextBlockStyle}" />
    </Border>

    <ListView Name="BrowseBySourceTopResultsListView" IsTabStop="True"
                x:FieldModifier="public"
                Grid.Row="3"
                SelectionMode="Single"
                IsItemClickEnabled="True"
                ItemClick="FeaturedResultsSourceListView_ItemClick"
                MaxHeight="500"                                                                             
                ItemsSource="{x:Bind BrowseBySourceList}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            </Style>
        </ListView.ItemContainerStyle>

        <ListView.ItemTemplate>
            <DataTemplate x:DataType="viewModels:BrowseByStarViewModel">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Image Source="{x:Bind icon}"
                            Width="40"
                            Height="40"
                            Margin="10"/>
                    <TextBlock Text="{x:Bind read}"
                                Grid.Column="1"
                                TextAlignment="Center"
                                VerticalAlignment="Center"
                                Margin="20, 0, 0, 0"/>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <AutoSuggestBox Grid.Row="1" 
                    Name="asbBrowseBySource"
                    TextMemberPath="read"    
                    PlaceholderText="{x:Bind ViewModel._TIPS_source_select}"      
                    LostFocus="asbBrowseBySource_LostFocus"                       
                    GotFocus="asbBrowseBySource_GotFocus"
                    TextChanged="asbBrowseBySource_TextChanged">
        <AutoSuggestBox.ItemTemplate>
            <DataTemplate x:DataType="response:ExploreApiResponseItem">
                <TextBlock Text="{x:Bind read}"
                           Margin="5"/>
            </DataTemplate>
        </AutoSuggestBox.ItemTemplate>
    </AutoSuggestBox>

    <ComboBox x:Name="BrowseBySourceComboBox"  
                LostFocus="BrowseBySourceComboBox_LostFocus"
                SelectionChanged="BrowseBySourceComboBox_SelectionChanged"
                Grid.Row="2"                                          
                PlaceholderText="{x:Bind ViewModel._TIPS_source_select}"      
                IsTextSearchEnabled="True"                                      
                Style="{StaticResource ComboBoxStyle}"
                ItemsSource="{x:Bind BrowseBySourceComboBoxList, Mode=OneWay}">

        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>
        <ComboBox.ItemTemplate>
            <DataTemplate x:DataType="response:ExploreApiResponseItem">
                <TextBlock Text="{x:Bind read}"
                            Margin="5"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>

    </ComboBox>
</Grid>

问题是,只要我打开ContentDialog,我的AutosuggestBox 就会自动聚焦。因为我在 AutosuggestBox 的 GotFocus 事件中设置了 IsSuggestionListOpen = True,所以在打开内容对话框后会立即打开建议列表。我想停止此操作并仅在用户单击/点击AutosuggestBOx 后打开 SuggestionList

为了补充这个问题,当 AutosuggestBox 已经聚焦并且我点击外面的某个地方时,它不会失去焦点。

【问题讨论】:

  • 尝试在ContentDialogLoaded 事件中关注其他内容。例如yourElement.Focus(FocusState.Programmatic);
  • 试过了,但是AutosuggestBox.GotFocusContentDialog.Opened之后被解雇了
  • 这可能是因为ContentDialog 不可聚焦所以它聚焦第一个可聚焦的孩子。尝试聚焦ComboBox
  • 那里打错字,编辑了我的评论,在我的ContentDialog.Opened 事件中,我将焦点从AutosuggestBox 移开

标签: c# xaml uwp


【解决方案1】:

尝试在AutoSuggestBox 和您的ListView 之间切换顺序,然后将ListViewIsTapStop 设置为True

<ListView Grid.Row="3" IsTabStop="True" ... />
<AutoSuggestBox Grid.Row="1" ... />

更新

ContentDialog 的默认样式中有一个Grid,它有一个默认的Padding(即ContentDialogPadding),它以某种方式阻止了LostFocus 的发生。

您可以通过删除此 Padding 并手动间隔其中的元素来解决此问题。

<Style TargetType="ContentDialog">
    <Setter Property="Foreground"
            Value="{ThemeResource ContentDialogForeground}" />
    <Setter Property="Background"
            Value="{ThemeResource ContentDialogBackground}" />
    <Setter Property="BorderBrush"
            Value="{ThemeResource ContentDialogBorderBrush}" />
    <Setter Property="HorizontalAlignment"
            Value="Center" />
    <Setter Property="VerticalAlignment"
            Value="Top" />
    <Setter Property="IsTabStop"
            Value="False" />
    <Setter Property="MaxHeight"
            Value="{ThemeResource ContentDialogMaxHeight}" />
    <Setter Property="MaxWidth"
            Value="{ThemeResource ContentDialogMaxWidth}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ContentDialog">
                <Border x:Name="Container">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ButtonsVisibilityStates">
                            <VisualState x:Name="AllVisible" />
                            <VisualState x:Name="NoneVisible">
                                <VisualState.Setters>
                                    <Setter Target="PrimaryButton.Visibility"
                                            Value="Collapsed" />
                                    <Setter Target="SecondaryButton.Visibility"
                                            Value="Collapsed" />
                                    <Setter Target="CloseButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="PrimaryVisible">
                                <VisualState.Setters>
                                    <Setter Target="PrimaryButton.(Grid.Column)"
                                            Value="2" />
                                    <Setter Target="PrimaryButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="PrimaryButton.Margin"
                                            Value="2,0,0,0" />
                                    <Setter Target="SecondaryButton.Visibility"
                                            Value="Collapsed" />
                                    <Setter Target="CloseButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="SecondaryVisible">
                                <VisualState.Setters>
                                    <Setter Target="SecondaryButton.(Grid.Column)"
                                            Value="2" />
                                    <Setter Target="SecondaryButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="SecondaryButton.Margin"
                                            Value="2,0,0,0" />
                                    <Setter Target="PrimaryButton.Visibility"
                                            Value="Collapsed" />
                                    <Setter Target="CloseButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="CloseVisible">
                                <VisualState.Setters>
                                    <Setter Target="CloseButton.(Grid.Column)"
                                            Value="2" />
                                    <Setter Target="CloseButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="CloseButton.Margin"
                                            Value="2,0,0,0" />
                                    <Setter Target="PrimaryButton.Visibility"
                                            Value="Collapsed" />
                                    <Setter Target="SecondaryButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="PrimaryAndSecondaryVisible">
                                <VisualState.Setters>
                                    <Setter Target="PrimaryButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="SecondaryButton.(Grid.Column)"
                                            Value="2" />
                                    <Setter Target="SecondaryButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="SecondaryButton.Margin"
                                            Value="2,0,0,0" />
                                    <Setter Target="CloseButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="PrimaryAndCloseVisible">
                                <VisualState.Setters>
                                    <Setter Target="PrimaryButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="CloseButton.(Grid.Column)"
                                            Value="2" />
                                    <Setter Target="CloseButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="CloseButton.Margin"
                                            Value="2,0,0,0" />
                                    <Setter Target="SecondaryButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="SecondaryAndCloseVisible">
                                <VisualState.Setters>
                                    <Setter Target="SecondaryButton.(Grid.Column)"
                                            Value="0" />
                                    <Setter Target="SecondaryButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="SecondaryButton.Margin"
                                            Value="0,0,2,0" />
                                    <Setter Target="CloseButton.(Grid.Column)"
                                            Value="2" />
                                    <Setter Target="CloseButton.(Grid.ColumnSpan)"
                                            Value="2" />
                                    <Setter Target="CloseButton.Margin"
                                            Value="2,0,0,0" />
                                    <Setter Target="PrimaryButton.Visibility"
                                            Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="DefaultButtonStates">
                            <VisualState x:Name="NoDefaultButton" />
                            <VisualState x:Name="PrimaryAsDefaultButton">
                                <VisualState.Setters>
                                    <Setter Target="PrimaryButton.Style"
                                            Value="{StaticResource AccentButtonStyle}" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="SecondaryAsDefaultButton">
                                <VisualState.Setters>
                                    <Setter Target="SecondaryButton.Style"
                                            Value="{StaticResource AccentButtonStyle}" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="CloseAsDefaultButton">
                                <VisualState.Setters>
                                    <Setter Target="CloseButton.Style"
                                            Value="{StaticResource AccentButtonStyle}" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid x:Name="LayoutRoot">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Border x:Name="BackgroundElement"
                                Background="{TemplateBinding Background}"
                                FlowDirection="{TemplateBinding FlowDirection}"
                                BorderThickness="{ThemeResource ContentDialogBorderWidth}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                MaxWidth="{TemplateBinding MaxWidth}"
                                MaxHeight="{TemplateBinding MaxHeight}"
                                MinWidth="{ThemeResource ContentDialogMinWidth}"
                                MinHeight="{ThemeResource ContentDialogMinHeight}">
                            <Grid x:Name="DialogSpace"
                                  VerticalAlignment="Stretch">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>
                                <ScrollViewer x:Name="ContentScrollViewer"
                                              HorizontalScrollBarVisibility="Disabled"
                                              VerticalScrollBarVisibility="Disabled"
                                              ZoomMode="Disabled"
                                              Margin="{ThemeResource ContentDialogContentScrollViewerMargin}"
                                              IsTabStop="False">
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto" />
                                            <RowDefinition Height="*" />
                                        </Grid.RowDefinitions>
                                        <ContentControl x:Name="Title"
                                                        Margin="{ThemeResource ContentDialogTitleMargin}"
                                                        Content="{TemplateBinding Title}"
                                                        ContentTemplate="{TemplateBinding TitleTemplate}"
                                                        FontSize="20"
                                                        FontFamily="XamlAutoFontFamily"
                                                        FontWeight="Normal"
                                                        Foreground="{TemplateBinding Foreground}"
                                                        HorizontalAlignment="Left"
                                                        VerticalAlignment="Top"
                                                        IsTabStop="False">
                                            <ContentControl.Template>
                                                <ControlTemplate TargetType="ContentControl">
                                                    <ContentPresenter Content="{TemplateBinding Content}"
                                                                      MaxLines="2"
                                                                      TextWrapping="Wrap"
                                                                      ContentTemplate="{TemplateBinding ContentTemplate}"
                                                                      Margin="{TemplateBinding Padding}"
                                                                      ContentTransitions="{TemplateBinding ContentTransitions}"
                                                                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                                                </ControlTemplate>
                                            </ContentControl.Template>
                                        </ContentControl>
                                        <ContentPresenter x:Name="Content"
                                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                                          Content="{TemplateBinding Content}"
                                                          FontSize="{ThemeResource ControlContentThemeFontSize}"
                                                          FontFamily="{ThemeResource ContentControlThemeFontFamily}"
                                                          Margin="{ThemeResource ContentDialogContentMargin}"
                                                          Foreground="{TemplateBinding Foreground}"
                                                          Grid.Row="1"
                                                          TextWrapping="Wrap" />
                                    </Grid>
                                </ScrollViewer>
                                <Grid x:Name="CommandSpace"
                                      Margin="24,0,24,24"
                                      Grid.Row="1"
                                      HorizontalAlignment="Stretch"
                                      VerticalAlignment="Bottom"
                                      XYFocusKeyboardNavigation="Enabled">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition />
                                        <ColumnDefinition Width="0.5*" />
                                        <ColumnDefinition Width="0.5*" />
                                        <ColumnDefinition />
                                    </Grid.ColumnDefinitions>
                                    <Button x:Name="PrimaryButton"
                                            Content="{TemplateBinding PrimaryButtonText}"
                                            IsEnabled="{TemplateBinding IsPrimaryButtonEnabled}"
                                            Style="{TemplateBinding PrimaryButtonStyle}"
                                            ElementSoundMode="FocusOnly"
                                            HorizontalAlignment="Stretch"
                                            VerticalAlignment="Stretch"
                                            Margin="0,0,2,0"
                                            Grid.Column="0" />
                                    <Button x:Name="SecondaryButton"
                                            Content="{TemplateBinding SecondaryButtonText}"
                                            IsEnabled="{TemplateBinding IsSecondaryButtonEnabled}"
                                            Style="{TemplateBinding SecondaryButtonStyle}"
                                            ElementSoundMode="FocusOnly"
                                            HorizontalAlignment="Stretch"
                                            VerticalAlignment="Stretch"
                                            Margin="2,0,2,0"
                                            Grid.Column="1"
                                            Grid.ColumnSpan="2" />
                                    <Button x:Name="CloseButton"
                                            Content="{TemplateBinding CloseButtonText}"
                                            Style="{TemplateBinding CloseButtonStyle}"
                                            ElementSoundMode="FocusOnly"
                                            HorizontalAlignment="Stretch"
                                            VerticalAlignment="Stretch"
                                            Margin="2,0,0,0"
                                            Grid.Column="3" />
                                </Grid>
                            </Grid>
                        </Border>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

上面的代码大部分来自默认样式,除了我做了两处改动-

  1. 我删除了DialogSpace 上的Padding
  2. 我给了CommandSpace 一个Margin24,0,24,24

最后,我在ContentDialog 内的顶级 级别Grid 中添加了默认的Padding24,18,24,0


更新 2

如果您想关闭AutoSuggestBoxPopup,您必须手动执行此操作。在其GotFocus 处理程序中,使用VisualTreeHelper 来定位背景矩形,并与它的Tapped 事件挂钩,因此无论何时点击它,您只需手动将IsSuggestionListOpen 设置为false。您还必须将焦点设置到另一个控件上。

var box = (AutoSuggestBox)sender;
box.IsSuggestionListOpen = true;

var popups = VisualTreeHelper.GetOpenPopups(Window.Current);
foreach (var popup in popups)
{
    if (popup.Child is Rectangle bg)
    {
        bg.Tapped += Bg_Tapped;

        void Bg_Tapped(object s, TappedRoutedEventArgs args)
        {
            bg.Tapped -= Bg_Tapped;

            box.IsSuggestionListOpen = false;
            BrowseBySourceTopResultsListView.Focus(FocusState.Programmatic);
        }
    }
}

【讨论】:

  • 很抱歉我没有提到它,但我正在实施 AutosuggestBox 来替换那个 ComboBox
  • 适用于第一部分,现在如何让 AutosuggestBox 失去焦点?
  • 所以当你在它外面点击时,它不会自动失去焦点?
  • 没有。在 ComboBox 的情况下,Combobox.LostFocusContentDialog.GotFocus 事件都不会被触发,但 ComboBox 列表仍然关闭。这里AutosuggestBox 两个事件都没有触发(但我希望关闭建议窗格)
  • 您通常根本不需要处理失去焦点的问题。你能展示更多你的xaml吗?如果您说在框外单击不会自动关闭窗格,则您的代码中可能存在其他错误。
【解决方案2】:

这是我的代码……是的,它很脏,但可以工作:) 此处理程序附加到内容对话框的“Opend”事件。

    private async void manageBoardsDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args)
    {
        // at first, disable the autosuggest control
        autoSuggestBox.IsEnabled = false;
        // do some async task
        // Set focus to another control 
        itemGridView.Focus(FocusState.Programmatic);
        // re-enable it
        autoSuggestBox.IsEnabled = true;
    }

【讨论】:

    【解决方案3】:

    UWP 将焦点放在可视树上的第一个可编辑控件上。因此,您可以添加一个可编辑控件,确保它在 UI 上不可见,即使它仍在 UI 上(不要启用/禁用 Visibility),然后将焦点设置到手动加载上的该控件以确保它收到重点。

    这是我之前遇到同样问题时所做的。

    在您的ContentDialog下面添加

    <TextBox x:Name="FocusedTextBox" Width="0" Height="0" Opacity="0" Margin="-5000,0,0,0" />
    

    现在在你的Loaded 中说

    FocusedTextBox.Focus(FocusState.Programmatic);
    

    【讨论】:

    • 这解决了最初的问题,现在如何通过单击外部任意位置使 AutosuggestBox 失去焦点。
    • @ravikumar 这也应该自动工作。 GotFocus 的任何控件在外部单击时都会自动失去焦点。
    • 整个内容都在 ContentDialog 内,您可能的意思是说,通过单击外部,ContentDialog 将获得焦点,而 AutosuggestBox 将失去焦点,但这不会发生
    • 我认为调用 Focus() 是个坏主意。如果您调试代码,您会注意到焦点最初仍会跳转到密码框。例如,假设讲述人已打开(或任何屏幕阅读器),它可能难以快速获取焦点的变化并最终阅读错误的内容,或者更糟糕的是,同时阅读密码框可访问文本和您实际想要的文本框焦点.. 一个好的解决方案是提示 Windows 知道哪些元素在焦点方面优先于其他元素。请参阅 Control.TabIndex :)
    猜你喜欢
    • 2017-11-24
    • 2018-01-20
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 1970-01-01
    相关资源
    最近更新 更多