Wpf 将焦点设置为ContentPresenter的内容
我需要将焦点设置为ContentPresenter的内容。我可以假设ContentTemplate包含一个IIInputElement,但不包含任何其他内容 下面是一个非常简单的示例,说明了问题: 主窗口:Wpf 将焦点设置为ContentPresenter的内容,wpf,focus,contentpresenter,Wpf,Focus,Contentpresenter,我需要将焦点设置为ContentPresenter的内容。我可以假设ContentTemplate包含一个IIInputElement,但不包含任何其他内容 下面是一个非常简单的示例,说明了问题: 主窗口: <Window x:Class="FiedControlTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.
<Window x:Class="FiedControlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:Esatto.Wpf.CustomControls;assembly=Esatto.Wpf.CustomControls"
xmlns:local="clr-namespace:FiedControlTest">
<Window.Resources>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Margin" Value="5"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding Path=Options}" Name="cbOptions" DisplayMemberPath="Description"/>
<Button Content="Set focus" Click="SetFocus"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="TextBox:"/>
<TextBox Name="tbText" Text="A bare text box."/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="ContentPresenter:"/>
<ContentPresenter Content="TextBox in a ContentPresenter" Name="cpText">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" IsReadOnly="True"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</StackPanel>
</StackPanel>
</Window>
代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
this.DataContext = this;
Options = new ObservableCollection<Option>(new[]{
new Option(){TargetType=typeof(TextBox), Description="Bare Text Box"},
new Option(){TargetType=typeof(ContentPresenter), Description="Content Presenter"}
});
InitializeComponent();
cbOptions.SelectedIndex = 0;
}
private void SetFocus(object sender, RoutedEventArgs e)
{
var opt = cbOptions.SelectedItem as Option;
if (opt.TargetType == typeof(TextBox))
tbText.Focus();
if (opt.TargetType == typeof(ContentPresenter))
cpText.Focus();
}
public ObservableCollection<Option> Options { get; set; }
public class Option
{
public Type TargetType { get; set; }
public string Description { get; set; }
}
}
那里没有多少。裸文本框按预期聚焦;ContentPresenter显示的文本框不存在
我曾尝试将Focusable=True添加到ContentPresenter,但没有任何明显的效果。我尝试使用Keyboard.SetFocus而不是UIElement.Focus,但行为没有改变
这是如何做到的?事实上,您设置的焦点是ContentPresenter,而不是内部文本框。因此,在本例中,您可以使用VisualTreeHelper在文本框中查找子视觉元素,并为其设置焦点。然而,如果IsReadOnly为真,您将不会看到任何插入符号闪烁,这可能也是您想要的。要在只读模式下显示,只需将IsReadOnlyCaretVisible设置为true: 此处添加了带IsReadOnlyCaretVisible的已编辑XAML代码:
请注意,上述代码仅适用于您使用文本框作为ContentPresenter的ContentTemplate的根可视模板的特定情况。在一般情况下,您需要一些递归方法来查找基于VisualTreeHelper的VisualChild,您可以对此进行更多搜索,我不想在这里包含它,因为在WPF中查找VisualChild是一个非常有名的问题/代码。斜体短语可以用作关键字来搜索更多内容。我一定写得不清楚。我不在乎背景色;这只是一个指标,使人们更容易一目了然地看到焦点所在。我感兴趣的是将键盘焦点放在那个文本框上,而不是内容演示者上。@mcwyrm我同意你的问题令人困惑,请查看我的更新答案。
private void SetFocus(object sender, RoutedEventArgs e)
{
var opt = cbOptions.SelectedItem as Option;
if (opt.TargetType == typeof(TextBox))
tbText.Focus();
if (opt.TargetType == typeof(ContentPresenter)) {
var child = VisualTreeHelper.GetChild(cpText, 0) as TextBox;
if(child != null) child.Focus();
}
}
<TextBox Text="{Binding Mode=OneWay}" IsReadOnly="True"
IsReadOnlyCaretVisible="True"/>