在WPF中的ControlTemplate内将控件设置为焦点

时间:2020-03-06 14:59:08  来源:igfitidea点击:

在我正在处理的应用程序中,我们有一堆自定义控件,它们的控件模板在Generic.xaml中定义。

例如,我们的自定义文本框将类似于以下内容:

<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中的特定控件上。

在我们的Ccode中,我们可以根据数据访问特定的" FieldTextBox"。一旦有了正确的FieldTextBox,就需要能够将焦点设置在ControlTemplate中包含的实际TextBox上。

我想出的最好的解决方案是在每个控件模板(在本例中为TextBox)的主控件上设置一个名称,例如" FocusableControl"。

然后将焦点设置在控件上的代码(包含在FieldTextBox的代码中)将是:

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

此解决方案有效。但是,还有其他人知道一个比这更有效的解决方案吗?

解决方案

在控件模板中,我们可以添加一个触发器,该触发器将StackPanel的FocusManager的FocusedElement设置为我们要聚焦的文本框。我们将触发器的属性设置为{TemplateBinding IsFocused},以便在焦点指向包含控件时触发。

我们可以通过提供一些DependancyProperty摆脱代码中控件名称的硬编码,并在DependancyProperty的controlLoaded或者OnApplyTemplate函数中使用相同的代码。
此DependancyProperty的发送者将是.Focus()调用的候选者。