在WPF中的控件模板中设置控件的焦点

3
在我正在处理的应用程序中,我们有一堆自定义控件,它们的ControlTemplates在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中特定控件的焦点。
在我们的C#代码中,我们可以根据数据找到特定的"FieldTextBox"。一旦我们找到正确的FieldTextBox,我们需要能够将焦点设置在ControlTemplate中包含的实际TextBox上。
我想到的最好的解决方案是给每个控制模板中的主要控件(在本例中为TextBox)设置一个名称,例如"FocusableControl"。
然后,在FieldTextBox的code-behind中,我的代码将设置焦点控件:
    Control control = (Control)this.Template.FindName("FocusableControl", this);
    if (control != null)
    {
        control.Focus();
    }

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

2个回答

2

在您的控件模板中,您可以添加一个触发器,将StackPanel的FocusManager的FocusedElement设置为您想要聚焦的文本框。您可以将触发器的属性设置为{TemplateBinding IsFocused},这样当包含控件获得焦点时,它就会触发。


ControlTemplate的触发器不需要使用TemplateBinding。只需将触发器的属性设置为“IsFocused”。这个解决方案是可行的,但我不确定它是否真的更有效率。 - Bob Wintemberg
1
如果您能详细说明您的解决方案,我们可能会在这里得到一个被接受的答案。我正在尝试做类似的事情,并且正在尝试使用您的建议进行实验,但是我并没有完全理解触发器的值绑定等其他细节。 - jpierson

0

通过提供一些依赖属性并根据依赖属性在controlLoaded或OnApplyTemplate函数中具有相同的代码,您可以消除代码中控件名称的硬编码。这个依赖属性的发送者将成为.Focus()调用的候选对象。


我不确定我完全理解你的解决方案。你能否更清楚地解释一下或者给一个简短的例子? - Bob Wintemberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接