WPF, фокусирующий элемент на показе окон - PullRequest
1 голос
/ 02 июля 2019

Я пытаюсь установить фокус на конкретный элемент при показе окна. Окно - это просто окно поиска / замены со вкладками; когда пользователь выбирает «Поиск», вкладка поиска активируется, и текстовое поле поиска должно получить фокус. Аналогично, когда пользователь выбирает «Заменить», активируется вкладка «Заменить», и текстовое поле «Замена» должно получить фокус.

Поскольку окно не является модальным, я снова его использую и скрываю вместо закрытия. Проблема в том, что фокус не получен должным образом. Скажи:

  • Я открываю Поиск. Окно показывает, текстовое поле поиска имеет фокус .
  • Я закрываю окно, затем открываю Заменить. Окно показывает, заменить текстовое поле не имеет фокуса
  • Я закрываю окно, затем снова открываю Заменить . Окно показывает, заменить текстовое поле имеет фокус .
  • Я закрываю окно, затем открываю Поиск. Текстовое поле поиска не имеет фокуса .
  • Я закрываю окно, затем снова открываю поиск . Текстовое поле поиска имеет фокус.

При открытии окна по выбору пользователя я вызываю один из следующих методов:

public void ChooseReplaceTab()
{
    tcTabs.SelectedItem = tReplace;
    FocusManager.SetFocusedElement(this, tbReplaceSearch);
    tbReplaceSearch.Focus();
}

public void ChooseSearchTab()
{
    tcTabs.SelectedItem = tSearch;
    FocusManager.SetFocusedElement(this, tbSearchSearch);
    tbSearchSearch.Focus();
}

В окне поиска нет ничего необычного, только набор вкладок, текстовых полей, радио и кнопок:

<Window x:Class="Dev.Editor.SearchReplaceWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Dev.Editor"
        xmlns:p="clr-namespace:Dev.Editor.Resources;assembly=Dev.Editor.Resources"
        xmlns:t="clr-namespace:Dev.Editor.BusinessLogic.Types.Search;assembly=Dev.Editor.BusinessLogic"
        mc:Ignorable="d"
        Title="{x:Static p:Strings.SearchWindow_Title}" SizeToContent="WidthAndHeight" ResizeMode="NoResize" Closing="HandleWindowClosing">
    <TabControl x:Name="tcTabs" Margin="{StaticResource DialogWindowPadding}">

        <!-- Search -->

        <TabItem x:Name="tSearch" Header="{x:Static p:Strings.SearchWindow_SearchTab}" >
            <GroupBox Header="{x:Static p:Strings.SearchWindow_SearchTab}" Padding="4">
                <StackPanel Orientation="Horizontal">
                    <StackPanel Orientation="Vertical">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="250" />
                            </Grid.ColumnDefinitions>

                            <Label Grid.Row="0" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_SearchedText}"/>
                            <TextBox x:Name="tbSearchSearch" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                        </Grid>

                        <GroupBox Header="{x:Static p:Strings.SearchWindow_SearchOptions}" Padding="4">
                            <StackPanel Orientation="Vertical">
                                <CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_CaseSensitive}" 
                                          IsChecked="{Binding CaseSensitive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                                <CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_OnlyFullWords}" 
                                          IsChecked="{Binding WholeWordsOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                                <CheckBox Content="{x:Static p:Strings.SearchWindow_SearchBackwards}" 
                                          IsChecked="{Binding SearchBackwards, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </StackPanel>
                        </GroupBox>
                        <GroupBox Header="{x:Static p:Strings.SearchWindow_SearchMode}" Padding="4">
                            <StackPanel Orientation="Vertical">
                                <RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeNormal}" 
                                             IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Normal}}"/>
                                <RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeExtended}" 
                                             IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Extended}}"/>
                                <RadioButton Content="{x:Static p:Strings.SearchWindow_SearchModeRegex}" 
                                             IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.RegularExpressions}}"/>
                            </StackPanel>
                        </GroupBox>
                    </StackPanel>
                    <StackPanel Orientation="Vertical" Margin="10,0,0,0">
                        <Button Content="{x:Static p:Strings.SearchWindow_FindNext}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding FindNextCommand}" />
                        <Button Content="{x:Static p:Strings.SearchWindow_Close}" Width="150" Command="{Binding CloseCommand}" />
                    </StackPanel>
                </StackPanel>
            </GroupBox>
        </TabItem>

        <TabItem x:Name="tReplace" Header="{x:Static p:Strings.SearchWindow_ReplaceTab}">
            <GroupBox Header="{x:Static p:Strings.SearchWindow_ReplaceTab}" Padding="4">
                <StackPanel Orientation="Horizontal">
                    <StackPanel Orientation="Vertical">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="250" />
                            </Grid.ColumnDefinitions>

                            <Label Margin="{StaticResource DialogItemsVMargin}" Grid.Row="0" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_SearchedText}"/>
                            <TextBox x:Name="tbReplaceSearch" Margin="{StaticResource DialogItemsVMargin}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" 
                                     Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

                            <Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_ReplaceWith}" />
                            <TextBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" 
                                     Text="{Binding Replace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                        </Grid>

                        <GroupBox Header="{x:Static p:Strings.SearchWindow_SearchOptions}" Padding="4">
                            <StackPanel Orientation="Vertical">
                                <CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_CaseSensitive}" 
                                          IsChecked="{Binding CaseSensitive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                <CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_OnlyFullWords}" 
                                          IsChecked="{Binding WholeWordsOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                <CheckBox Content="{x:Static p:Strings.SearchWindow_SearchBackwards}" 
                                          IsChecked="{Binding SearchBackwards, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </StackPanel>
                        </GroupBox>
                        <GroupBox Header="{x:Static p:Strings.SearchWindow_SearchMode}" Padding="4">
                            <StackPanel Orientation="Vertical">
                                <RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeNormal}" 
                                             IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Normal}}"/>
                                <RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeExtended}" 
                                             IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Extended}}"/>
                                <RadioButton Content="{x:Static p:Strings.SearchWindow_SearchModeRegex}" 
                                             IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.RegularExpressions}}"/>
                            </StackPanel>
                        </GroupBox>
                    </StackPanel>
                    <StackPanel Orientation="Vertical" Margin="10,0,0,0">
                        <Button Content="{x:Static p:Strings.SearchWindow_FindNext}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding FindNextCommand}" />
                        <Button Content="{x:Static p:Strings.SearchWindow_Replace}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding ReplaceCommand}"/>
                        <Separator Margin="{StaticResource DialogItemsVMargin}" />
                        <Button Content="{x:Static p:Strings.SearchWindow_ReplaceAll}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding ReplaceAllCommand}"/>
                        <CheckBox Content="{x:Static p:Strings.SearchWindow_InSelection}" Margin="{StaticResource DialogItemsVMargin}" 
                                  IsEnabled="{Binding SelectionAvailable}" IsChecked="{Binding ReplaceAllInSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        <Separator Margin="{StaticResource DialogItemsVMargin}" />
                        <Button Content="{x:Static p:Strings.SearchWindow_Close}" Width="150" Command="{Binding CloseCommand}"></Button>
                    </StackPanel>
                </StackPanel>
            </GroupBox>
        </TabItem>
    </TabControl>
</Window>

Что я должен сделать, чтобы правильно установить фокус на конкретный элемент при вызове этих методов?

1 Ответ

2 голосов
/ 02 июля 2019

Вы можете попробовать что-то вроде этого:

Dispatcher.BeginInvoke(
    DispatcherPriority.ContextIdle,
    new Action(delegate()
    {
        tbSearchSearch.Focus();
    }));

По этой ссылке: Альтернатива для установки фокуса из события Enter

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...