在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()调用的候选者。