在我正在处理的应用程序中,我们有一堆自定义控件,其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的代码隐藏中)然后将焦点设置在控件上:
Control control = (Control)this.Template.FindName("FocusableControl", this);
if (control != null)
{
control.Focus();
}
此解决方案有效。但是,是否有其他人知道一种比这更有效的解决方案?
答案 0 :(得分:2)
在控件模板中,您可以添加一个Trigger,将StackPanel的FocusManager的FocusedElement设置为您想要关注的文本框。您将Trigger的属性设置为{TemplateBinding IsFocused},以便在关注包含控件时触发。
答案 1 :(得分:0)
您可以通过提供一些DependancyProperty来消除代码中控件名称的硬编码,并在基于DependancyProperty的controlLoaded或OnApplyTemplate函数中使用相同的代码。 这个DependancyProperty的发送者将成为.Focus()调用的候选者。