C# 在 WPF 中的 ControlTemplate 中的控件上设置焦点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/158536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting Focus on a Control within a ControlTemplate in WPF
提问by Bob Wintemberg
In an application I'm working on, we have a bunch of custom controls with their ControlTemplates defined in Generic.xaml.
在我正在处理的应用程序中,我们有一堆自定义控件,它们的 ControlTemplates 定义在 Generic.xaml 中。
For instance, our custom textbox would look similar to this:
例如,我们的自定义文本框看起来类似于:
<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>
In our application, we need to be able to programatically set the focus on a particular control within the ControlTemplate.
在我们的应用程序中,我们需要能够以编程方式将焦点设置在 ControlTemplate 中的特定控件上。
Within our C# code, we can get to the particular "FieldTextBox" based on our data. Once we have the correct FieldTextBox, we need to be able to set the focus on the actual TextBox contained within the ControlTemplate.
在我们的 C# 代码中,我们可以根据我们的数据访问特定的“FieldTextBox”。一旦我们有了正确的 FieldTextBox,我们就需要能够将焦点设置在 ControlTemplate 中包含的实际 TextBox 上。
The best solution I've come up with is to set a name on the primary control in each control template (in this case it's the TextBox), such as "FocusableControl."
我想出的最佳解决方案是在每个控件模板(在本例中为 TextBox)的主控件上设置一个名称,例如“FocusableControl”。
My code (contained in the code-behind for the FieldTextBox) to then set focus on the control would be:
我的代码(包含在 FieldTextBox 的代码隐藏中)然后将焦点设置在控件上将是:
Control control = (Control)this.Template.FindName("FocusableControl", this);
if (control != null)
{
control.Focus();
}
This solution works. However, does anyone else know of a solution that would be more efficient than this?
此解决方案有效。但是,有没有其他人知道比这更有效的解决方案?
回答by Bob Wintemberg
Within your control template you can add a Trigger that sets the FocusedElement of the StackPanel's FocusManagerto the textbox you want focused. You set the Trigger's property to {TemplateBinding IsFocused} so it fires when the containing control is focused.
在您的控件模板中,您可以添加一个触发器,将 StackPanel 的FocusManager的 FocusedElement 设置为您想要聚焦的文本框。您将 Trigger 的属性设置为 {TemplateBinding IsFocused},以便在包含控件获得焦点时触发。
回答by Jobi Joy
You can get rid of the hard coding of control name in the code by providing some DependancyProperty and have the same code in controlLoaded or OnApplyTemplate function based on the DependancyProperty. This DependancyProperty's sender will the candidate for .Focus() call.
您可以通过提供一些 DependancyProperty 来摆脱代码中控件名称的硬编码,并在基于 DependancyProperty 的 controlLoaded 或 OnApplyTemplate 函数中具有相同的代码。此 DependancyProperty 的发送者将成为 .Focus() 调用的候选者。