2015-07-21 2 views
1

В моем приложении у меня есть TabControl. На одном TabItem есть три TextBoxes, где я могу переключаться между ними, нажимая Tab-Key.Tab-Focus на пользовательском TextBox

Теперь я хочу заменить этот стандарт TextBoxes на custom-TextBoxes, который должен иметь нуль-текст, который будет отображаться, если текст пуст.

Часть XAML моей нестандартной TextBox является:

<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 зарегистрированы.

My default- TextBox ведет себя так, как я ожидаю. Но если я нажимаю клавишу Tab, а фокус находится в пределах одного NullTextBox, фокус переключается на TabHeader, а не на второй NullTextBox.

Часть XAML, где NullTextBoxes расположены он выглядит следующим образом:

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

Почему мой второй и третий NullTextBox не получают сосредоточенным, когда я нажимаю Tab-Key?


Я выяснил, что если я удалю 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

Я пытался использовать вас UserControl, и я не нашел какой-либо вопрос. Какую платформу .NET вы используете? Можете ли вы разместить свой код UserControl и код конвертера, пожалуйста? –

+0

Если все NullTextBox делает что-то, если значение равно null, почему бы просто не установить «TargetNullValue» в базе привязки обычного TextBox, например '{Binding Blah, TargetNullValue = 'Введите текст здесь ...'}'? –

+0

Я хочу, чтобы NullText был в темно-сером и в курсивом стиле. – Tomtom

ответ

1

Измените TextBlock внутри вашего Гиперссылка для Запустите, как это (обратите внимание, что s осле Run не поддерживает VerticalAlignment или Margin, я либо удалить или переместить эти свойства):

<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-Key два раза. Кто улавливает фокус после первого нажатия клавиши табуляции? – Tomtom

+0

Возможно, сам 'UserControl'. У вас это как «Focusable =« True ». Попытайтесь установить его на «False» и посмотреть, разрешит ли он это. – almulo

+0

Если это не решит проблему, просто проверьте все элементы управления внутри вашего UserControl ... Все они, кроме TextBox, должны иметь либо «Фокусное», либо «IsTabStop» на «False». Он работал сразу в моем примере с кодом, который я предоставил, так что, возможно, это из-за некоторой модификации, которую вы сделали после размещения кода здесь. – almulo

Смежные вопросы