2008-10-01 3 views
3

В приложении, над которым я работаю, у нас есть куча пользовательских элементов управления с их ControlTemplates, определенными в Generic.xaml.Настройка фокуса на элемент управления в ControlTemplate в WPF

Например, наш обычай текстовое поле будет выглядеть примерно так:

<Style TargetType="{x:Type controls:FieldTextBox}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type controls:FieldTextBox}"> 
       <Border BorderThickness="0" Margin="5"> 
        <StackPanel ToolTip="{Binding Path=Field.HintText, RelativeSource={RelativeSource TemplatedParent}}"> 
         <TextBlock Text="{Binding Path=Field.FieldLabel, RelativeSource={RelativeSource TemplatedParent}}" 
            HorizontalAlignment="Left" 
            /> 
         <TextBox Width="{Binding Path=Field.DisplayWidth, RelativeSource={RelativeSource TemplatedParent}}" 
           HorizontalAlignment="Left" 
           Text="{Binding Path=Field.Data.CurrentValue, RelativeSource={RelativeSource TemplatedParent}}" 
           IsEnabled="{Binding Path=Field.IsEnabled, RelativeSource={RelativeSource TemplatedParent}}" 
           ContextMenu="{Binding Source={StaticResource FieldContextMenu}}" > 
          <TextBox.Background> 
           <SolidColorBrush Color="{Binding Path=Field.CurrentBackgroundColor, RelativeSource={RelativeSource TemplatedParent}}"/> 
          </TextBox.Background> 
         </TextBox> 
        </StackPanel> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="Focusable" Value="True" /> 
    <Setter Property="IsTabStop" Value="False" /> 
</Style> 

В нашем приложении, мы должны иметь возможность программно установить фокус на конкретном элементе управления в пределах ControlTemplate.

В рамках нашего кода на C# мы можем перейти к конкретному «FieldTextBox» на основе наших данных. Как только у нас есть правильный FieldTextBox, мы должны уметь сосредоточиться на фактическом TextBox, содержащемся в ControlTemplate.

Лучшее решение, с которым я столкнулся, - установить имя в основном элементе управления в каждом шаблоне управления (в данном случае это TextBox), например, «FocusableControl».

Мой код (содержащийся в коде-позади для FieldTextBox), чтобы затем установить фокус на элементе управления будет:

Control control = (Control)this.Template.FindName("FocusableControl", this); 
    if (control != null) 
    { 
     control.Focus(); 
    } 

Это решение работает. Однако знает ли кто-нибудь о решении, которое было бы более эффективным, чем это?

ответ

2

В шаблоне управления вы можете добавить триггер, который устанавливает FocusedElement of StackPanel FocusManager в текстовое поле, которое вы хотите сфокусировать. Вы устанавливаете свойство Trigger {TemplateBinding IsFocused}, чтобы он срабатывал, когда сдерживающий элемент управления сфокусирован.

+0

TemplateBinding не требуется для триггера ControlTemplate. Просто установите свойство триггера «IsFocused». Решение работает, однако я не уверен, действительно ли он эффективнее. – 2008-10-01 18:11:23

+1

Мы могли бы получить принятый ответ здесь, если бы вы могли подробнее остановиться на своем решении. Я пытаюсь сделать что-то подобное, и я экспериментирую с вашими предложениями, но я не полностью понимаю, что привязка значения триггера будет выглядеть среди других деталей. – jpierson 2011-02-11 02:47:44

0

Вы можете избавиться от жесткого кодирования управляющего имени в коде, предоставив некоторый DependancyProperty и иметь один и тот же код в функции controlLoaded или OnApplyTemplate на основе DependancyProperty. Этот отправитель DependancyProperty будет кандидатом на вызов .Focus().