2014-11-21 95 views
0

我需要将焦点设置为ContentPresenter的内容。我可以假设ContentTemplate包含一个IInputElement,但没有其他任何关于它的内容。将焦点设置为ContentPresenter的内容

这里是一个大大简化的例子,说明了这个问题:

主窗口:

<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; } 
    } 
} 

没有太多的存在。正如预期的那样,裸露的TextBox重点关注;由ContentPresenter提供的TextBox没有。

我曾尝试将Focusable="True"添加到ContentPresenter,但它没有任何可见的效果。我尝试过使用Keyboard.SetFocus而不是UIElement.Focus,但行为不会改变。

这是如何完成的?

回答

0

实际上你设定的重点是ContentPresenter,而不是内部的TextBox。因此,您可以使用VisualTreeHelper来查找子视觉元素(本例中为TextBox)并为其设置焦点。但IsReadOnlytrue,你不会看到任何插入符号闪烁(这也可能是你想要的)。要显示它以只读模式,我们可以只设置IsReadOnlyCaretVisibletrue

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(); 
    }    
} 

这里与IsReadOnlyCaretVisible编辑的XAML代码添加:

<TextBox Text="{Binding Mode=OneWay}" IsReadOnly="True" 
     IsReadOnlyCaretVisible="True"/> 

注意上面的代码只能在您的具体应用如果您使用TextBox作为ContentPresenter的ContentTemplate的根视觉效果。在一般情况下,您将需要一些递归方法来查找子视觉(基于VisualTreeHelper),您可以搜索更多信息,我不想将其包含在此处,因为它是WPF中非常有名的问题/代码, 找到WPF中的可视化子项。 (斜体短语可以用作关键字来搜索更多)。

+1

我一定没写清楚。我不关心背景颜色;这只是作为一个指标,让人们一眼就能看到焦点所在。我*有兴趣将键盘焦点放到该文本框上,而不是内容提供者。 – mcwyrm 2014-11-22 10:21:41

+0

@mcwyrm我同意你的问题很混乱,请看我更新的答案。 – 2014-11-22 13:23:33