2014-11-21 141 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