2015-07-21 131 views
1

在我的應用程序中,我有一個TabControl。在一個TabItem有三個TextBoxes,我可以通過按Tab鍵在它們之間切換。Tab-Focus on custom TextBox

現在我想用custom- TextBoxes替換這個標準TextBoxes,它應該有一個空文本,如果文本是空的,將顯示空文本。

我定做TextBox的XAML是:

<UserControl x:Class="MyApplication.Controls.NullTextTextBox" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:converter="clr-namespace:ScM.Converter" 
      mc:Ignorable="d" d:DesignHeight="24" d:DesignWidth="300" 
      x:Name="nullTextTextBox" IsHitTestVisible="True" Focusable="True"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <TextBox Grid.Column="0" VerticalAlignment="Stretch" x:Name="tbInput" 
       Text="{Binding ElementName=nullTextTextBox,Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
       AcceptsReturn="{Binding ElementName=nullTextTextBox, Path=AcceptsReturn, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
       TextWrapping="{Binding ElementName=nullTextTextBox, Path=TextWrapping, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
       IsTabStop="True" /> 
     <TextBlock Grid.Column="0" VerticalAlignment="Top" Text="{Binding ElementName=nullTextTextBox,Path=NullText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" 
        FontStyle="Italic" Foreground="DarkGray" Margin="4,4,0,0" IsHitTestVisible="False" 
        Visibility="{Binding ElementName=nullTextTextBox, Path=Text, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, Converter={converter:StringIsNullToVisibilityConverter}}" 
        Focusable="False"/> 
     <TextBlock Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"> 
      <TextBlock.Visibility> 
       <MultiBinding Converter="{converter:DeleteButtonMultiConverter}"> 
        <Binding ElementName="nullTextTextBox" Path="IsClearButtonVisible" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/> 
        <Binding ElementName="nullTextTextBox" Path="Text" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/> 
       </MultiBinding> 
      </TextBlock.Visibility> 
      <Hyperlink TextDecorations="{x:Null}" Command="{Binding ElementName=nullTextTextBox, Path=ClearTextCommand, Mode=OneWay}" 
         Focusable="False" > 
       <TextBlock FontFamily="Wingdings 2" Text="Î" Foreground="Red" FontWeight="Bold" FontSize="14" VerticalAlignment="Center" Margin="1,1,2,1"/> 
      </Hyperlink> 
     </TextBlock> 
    </Grid> 
</UserControl> 

我會說這XAML的代碼隱藏是不相關的,因爲只有註冊DependencyProperties

我的默認-TextBox的行爲就像我期望的那樣。但是,如果在焦點位於一個NullTextBox內時按下Tab鍵,焦點將切換到TabHeader而不是第二個NullTextBox。

其中NullTextBoxes位於它看起來像XAML:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 
    <controls:NullTextTextBox Grid.Row="0" NullText="Value 1"/> 
    <controls:NullTextTextBox Grid.Row="1" NullText="Value 2"/> 
    <controls:NullTextTextBox Grid.Row="2" NullText="Value 3"/> 
</Grid> 

爲什麼當我按下Tab密鑰我的第二和第三NullTextBox沒有得到關注?


我發現如果刪除包含超鏈接的TextBlock,Tab-Order按預期工作。但我需要這個TextBlock的...


我的自定義文本框的後臺代碼的樣子:

public partial class NullTextTextBox : UserControl, INotifyPropertyChanged 
{ 
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
     "Text", typeof (string), typeof (NullTextTextBox), new PropertyMetadata(default(string))); 

    public static readonly DependencyProperty NullTextProperty = DependencyProperty.Register(
     "NullText", typeof (string), typeof (NullTextTextBox), new PropertyMetadata(default(string))); 

    public static readonly DependencyProperty IsClearButtonVisibleProperty = DependencyProperty.Register(
     "IsClearButtonVisible", typeof (bool), typeof (NullTextTextBox), new PropertyMetadata(default(bool))); 

    public static readonly DependencyProperty AcceptsReturnProperty = DependencyProperty.Register(
     "AcceptsReturn", typeof (bool), typeof (NullTextTextBox), new PropertyMetadata(default(bool))); 

    public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register(
     "TextWrapping", typeof (TextWrapping), typeof (NullTextTextBox), new PropertyMetadata(default(TextWrapping))); 

    public TextWrapping TextWrapping 
    { 
     get { return (TextWrapping) GetValue(TextWrappingProperty); } 
     set 
     { 
      SetValue(TextWrappingProperty, value); 
      OnPropertyChanged(); 
     } 
    } 

    private ICommand clearTextCommand; 

    public NullTextTextBox() 
    { 
     InitializeComponent(); 
     IsClearButtonVisible = false; 
     Text = string.Empty; 
     NullText = "Enter text here..."; 
     AcceptsReturn = false; 
     TextWrapping = TextWrapping.NoWrap; 
    } 

    public bool AcceptsReturn 
    { 
     get { return (bool) GetValue(AcceptsReturnProperty); } 
     set 
     { 
      SetValue(AcceptsReturnProperty, value); 
      OnPropertyChanged(); 
     } 
    } 

    public ICommand ClearTextCommand 
    { 
     get { return clearTextCommand ?? (clearTextCommand = new RelayCommand<object>(p => ClearText())); } 
    } 

    public bool IsClearButtonVisible 
    { 
     get { return (bool) GetValue(IsClearButtonVisibleProperty); } 
     set 
     { 
      SetValue(IsClearButtonVisibleProperty, value); 
      OnPropertyChanged(); 
     } 
    } 

    public string Text 
    { 
     get { return (string) GetValue(TextProperty); } 
     set 
     { 
      SetValue(TextProperty, value); 
      OnPropertyChanged(); 
     } 
    } 

    public string NullText 
    { 
     get { return (string) GetValue(NullTextProperty); } 
     set 
     { 
      SetValue(NullTextProperty, value); 
      OnPropertyChanged(); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void ClearText() 
    { 
     Text = string.Empty; 
     tbInput.Focus(); 
    } 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

和使用轉換器:

internal class DeleteButtonMultiConverter : MarkupExtension, IMultiValueConverter 
{ 
    private static DeleteButtonMultiConverter converter; 

    public DeleteButtonMultiConverter() 
    { 

    } 

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (values != null && values.Length == 2 && values[0] is bool && values[1] is string) 
     { 
      if ((bool) values[0] && !string.IsNullOrEmpty((string) values[1])) 
       return Visibility.Visible; 
      return Visibility.Collapsed; 
     } 
     return values; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return converter ?? (converter = new DeleteButtonMultiConverter()); 
    } 
} 
+0

我試圖用你用戶控件,我並沒有發現任何問題。你使用哪種.NET框架?你可以發佈你的UserControl代碼和你的轉換器代碼嗎? –

+0

如果所有的Nu​​llTextBox的do都顯示一些東西,如果這個值爲null,那麼爲什麼不直接在一個常規TextBox的綁定庫中設置一個'TargetNullValue',比如'{Binding Blah,TargetNullValue ='在這裏輸入文本...'}'? –

+0

我希望NullText爲深灰色和斜體樣式。 – Tomtom

回答

1

更改TextBlock的在你的超鏈接運行,像這樣(注意,s因斯運行不支持VerticalAlignmentMargin,我要麼刪除或移動這些屬性):

<TextBlock Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="1,1,2,1"> 
    <TextBlock.Visibility> 
     <MultiBinding Converter="{converter:DeleteButtonMultiConverter}"> 
      <Binding ElementName="nullTextTextBox" Path="IsClearButtonVisible" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/> 
      <Binding ElementName="nullTextTextBox" Path="Text" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/> 
     </MultiBinding> 
    </TextBlock.Visibility> 
    <Hyperlink TextDecorations="{x:Null}" Command="{Binding ElementName=nullTextTextBox, Path=ClearTextCommand, Mode=OneWay}" 
       Focusable="False" > 
     <Run FontFamily="Wingdings 2" Text="Î" Foreground="Red" FontWeight="Bold" FontSize="14" /> 
    </Hyperlink> 
</TextBlock> 
+0

好的。現在我可以通過按Tab鍵兩次來切換焦點。在第一次按Tab鍵後,誰抓住了焦點? – Tomtom

+0

可能是'UserControl'本身。你把它當作'Focusable =「True」'。嘗試將其設置爲「假」,看看是否能解決這個問題。 – almulo

+0

如果這樣不能解決問題,只需檢查UserControl內的所有控件......除TextBox外,其他所有控件都應具有「Focusable」或「IsTabStop」爲「False」。它在我提供的代碼示例中馬上工作,所以也許是因爲您在此處發佈代碼後進行了一些修改。 – almulo