WPF: Фокус в окне и UserControl - PullRequest
0 голосов
/ 04 марта 2010

Я пытаюсь получить пользовательский элемент управления для вкладки должным образом и сбит с толку. Логическое дерево выглядит следующим образом.

|-Window
  -Grid
    -TabControl
      -TabItem
        -StackPanel
          -MyUserControl
            |-StackPanel
              -GroupBox
                -Grid
                  -ComboBox
                    -Textbox1
                      -Textbox2

Все работает нормально, за исключением случаев, когда преобразователь видимости для ComboBox возвращает Visibility.Collapsed (не разрешать пользователю изменять режим базы данных), а затем, когда выбран textbox1, вместо возможности перемещаться по элементам управления в UserControl, фокус смещается на кнопку, объявленную в нижней части окна. Ничто, кроме отображаемых элементов управления, не имеет установленных свойств TabIndex или FocusManager.

Я бьюсь головой о кирпичную стену и, должно быть, что-то упускаю. Я пробовал IsFocusScope = True / False, играл с FocusedElement и ничего не работает, если этот ComboBox невидим (Visibility.Collapsed).

<Window x:Class="MyNamespace.Client.WinInstaller"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    FocusManager.FocusedElement="{Binding ElementName=tabWizard}">
    <Window.Resources>
        <props:Settings x:Key="settings" />
    </Window.Resources>
    <Grid Grid.IsSharedSizeScope="True">
        <!-- row and column definitions omitted -->

        <loc:SmallHeader Grid.Row="0" x:Name="headerBranding" HeaderText="Setup" />
        <TabControl x:Name="tabWizard" DataContext="{StaticResource settings}" SelectedIndex="0" FocusManager.IsFocusScope="True">
            <TabItem x:Name="tbStart" Height="0">
                <StackPanel>
                    <TextBlock Text="Database Mode"/>
                    <loc:DatabaseSelector x:Name="dbSelector" AllowChangeMode="False" TabIndex="1"
                                          AvailableDatabaseModes="SQLServer" IsPortRequired="False"
                                          DatabaseMode="{Binding Default.DbMode,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                          DatabasePath="{Binding Default.DatabasePath,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                </StackPanel>
            </TabItem>
        ...

Верхняя часть пользовательского элемента управления находится ниже:

<UserControl x:Class="MyNamespace.Client.DatabaseSelector"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="root"
    FocusManager.IsFocusScope="True"
    FocusManager.FocusedElement="{Binding ElementName=cboDbMode}">
    <UserControl.Resources>
        <conv:DatabaseModeIsFileBased x:Key="DatabaseModeIsFileBased"/>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </UserControl.Resources>
    <StackPanel DataContext="{Binding}">
        <GroupBox>
            <Grid>
                <!-- row and column definitions omitted -->
                <Label Content="Database Mode"/>
                <ComboBox x:Name="cboDbMode" SelectedValue="{Binding ElementName=root,Path=DatabaseMode,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                          DisplayMemberPath="Value" SelectedValuePath="Key" TabIndex="1" Visibility="{Binding AllowChangeMode,ElementName=root,Converter={StaticResource BooleanToVisibilityConverter}}" />
                   <!-- AllowChangeMode is a DependencyProperty on the UserControl -->
                <Grid><!-- row and column definitions omitted -->
                    <Label "Host"/>
                    <TextBox x:Name="txtDBHost" Text="{Binding ElementName=root,Path=DatabaseHost,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" TabIndex="2" />
                    <TextBox x:Name="txtDBPort" Text="{Binding ElementName=root,Path=DatabasePortString,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" TabIndex="3" />

Ответы [ 2 ]

4 голосов
/ 14 мая 2011

Я знаю, что этот ответ довольно поздно ... но вы пробовали:

<UserControl ... KeyboardNavigation.TabNavigation="Local">

Это обеспечит, как только ваш UserControl получит фокус, вы будете перемещаться только через TabStop в вашем UserControl (вместо того, чтобы беспокоиться о конфликте значений TabIndex во всем приложении). После циклического перемещения по TabStops вашего UserControl TabNavigation снова перейдет к TabStop за его пределами.

http://msdn.microsoft.com/en-us/library/system.windows.input.keyboardnavigationmode.aspx

0 голосов
/ 26 марта 2010

Возможно, проблема в том, что вы скрываете FocusManager.FocusedElement.В любом случае, вы можете упростить жизнь, просто устранив некоторые усложняющие факторы:

  1. Удалите FocusManager.FocusedElement ... ComboBox - это первый элемент управления в любом случае.
  2. Удалите FocusManager.IsFocusScope... Я полагаю, это нормально, если каждый раз, когда вы вводите пользовательский элемент управления, будет фокусироваться первый элемент управления внутри, а не тот, который был сфокусирован, когда вы покидали его раньше.Просто позвольте usercontrol быть «встроенным» в окружающие элементы управления.
  3. Удалите явные TabIndices в UserControl.Ваш макет уже подразумевает тот же порядок.

Если вы устраните эти три усложняющих фактора, возможно, вы уже сделали.Возможно, вам также нужно установить UserControl Focusable = False, чтобы фокус передавался первому фокусируемому элементу управления внутри - comboBox или TextBox1.

...