Tab-Focus on custom TextBox
问题描述:
在我的应用程序中,我有一个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());
}
}
答
更改TextBlock的在你的超链接为运行,像这样(注意,s因斯运行不支持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>
我试图用你用户控件,我并没有发现任何问题。你使用哪种.NET框架?你可以发布你的UserControl代码和你的转换器代码吗? –
如果所有的NullTextBox的do都显示一些东西,如果这个值为null,那么为什么不直接在一个常规TextBox的绑定库中设置一个'TargetNullValue',比如'{Binding Blah,TargetNullValue ='在这里输入文本...'}'? –
我希望NullText为深灰色和斜体样式。 – Tomtom