自定义控件未呈现
下面的控件背后的想法是能够在没有任何文本时在文本框内显示标签。为此,我只使用了一个类似的工作控件,即 SearchTextBox,但有太多功能无法满足我的需要。
我怀疑下面样式的控制模板,但我没有发现它有任何明显的问题。不过,我很容易会错过一些对于有更多经验的人来说显而易见的东西。
我该如何修复或排除此问题?
干杯,
Berryl
代码
/// <summary>Light weight version of a <see cref="SearchTextBox"/></summary>
public class LabelTextBox : TextBox
{
#region Dependency Properties
#region Label Text
/// <summary>Sets the 'watermark' text that acts as a label, identifying what this will search for.</summary>
public static readonly DependencyProperty LabelTextProperty =
DependencyProperty.Register("LabelText",
typeof (string), typeof (LabelTextBox), new PropertyMetadata("Search"));
public string LabelText
{
get { return (string) GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
/// <summary>Brush for the label text.</summary>
public static readonly DependencyProperty LabelTextColorProperty =
DependencyProperty.Register("LabelTextColor", typeof (Brush), typeof (LabelTextBox));
public Brush LabelTextColor
{
get { return (Brush)GetValue(LabelTextColorProperty); }
set { SetValue(LabelTextColorProperty, value); }
}
#endregion
#region Has Text
private static readonly DependencyPropertyKey HasTextPropertyKey =
DependencyProperty.RegisterReadOnly("HasText",
typeof (bool), typeof (LabelTextBox), new PropertyMetadata());
/// <summary>True if the user has typed in text.</summary>
public static readonly DependencyProperty HasTextProperty = HasTextPropertyKey.DependencyProperty;
public bool HasText
{
get { return (bool)GetValue(HasTextProperty); }
private set { SetValue(HasTextPropertyKey, value); }
}
#endregion
#endregion
#region Construction
static LabelTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof (LabelTextBox), new FrameworkPropertyMetadata(typeof (LabelTextBox)));
}
#endregion
#region Event Handlers
protected override void OnTextChanged(TextChangedEventArgs e)
{
base.OnTextChanged(e);
HasText = Text.Length != 0;
}
#endregion
}
风格
<Style x:Key="{x:Type cc:LabelTextBox}" TargetType="{x:Type cc:LabelTextBox}">
<Setter Property="Background" Value="{StaticResource SearchTextBox_Background}" />
<Setter Property="BorderBrush" Value="{StaticResource SearchTextBox_Border}" />
<Setter Property="Foreground" Value="{StaticResource SearchTextBox_Foreground}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="LabelText" Value="Search" />
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="LabelTextColor" Value="{StaticResource SearchTextBox_LabelTextColor}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:LabelTextBox}">
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" Padding="2"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
>
<Grid x:Name="LayoutGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="PART_ContentHost" Grid.Column="0" />
<Label x:Name="LabelText" Grid.Column="0"
Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelTextColor}"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelText}"
Padding="2,0,0,0" FontStyle="Italic"
/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!--input triggers (mouse over && keyboard focused-->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SearchTextBox_BorderMouseOver}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SearchTextBox_BorderMouseOver}" />
</Trigger>
<!--Once the user has typed in search text-->
<Trigger Property="HasText" Value="True">
<!--Hide the label text-->
<Setter Property="Visibility" TargetName="LabelText" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--
Error display
-->
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right" Text=" *"
Foreground="Red"
FontWeight="Bold" FontSize="16"
ToolTip="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="placeholder"></AdornedElementPlaceholder>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="LightYellow"/>
</Trigger>
</Style.Triggers>
</Style>
The idea behind the control below is to be able to show a Label inside of a TextBox when there isn't any text. To do this, I just took a working control that is similar, a SearchTextBox, but has too much going on for what I need here.
I suspect the control template in the style below but I don't see any thing obviously wrong with it. I could easily be missing something that is obvious to someone with more experience though.
How do I fix or trouble shoot this?
Cheers,
Berryl
Code
/// <summary>Light weight version of a <see cref="SearchTextBox"/></summary>
public class LabelTextBox : TextBox
{
#region Dependency Properties
#region Label Text
/// <summary>Sets the 'watermark' text that acts as a label, identifying what this will search for.</summary>
public static readonly DependencyProperty LabelTextProperty =
DependencyProperty.Register("LabelText",
typeof (string), typeof (LabelTextBox), new PropertyMetadata("Search"));
public string LabelText
{
get { return (string) GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
/// <summary>Brush for the label text.</summary>
public static readonly DependencyProperty LabelTextColorProperty =
DependencyProperty.Register("LabelTextColor", typeof (Brush), typeof (LabelTextBox));
public Brush LabelTextColor
{
get { return (Brush)GetValue(LabelTextColorProperty); }
set { SetValue(LabelTextColorProperty, value); }
}
#endregion
#region Has Text
private static readonly DependencyPropertyKey HasTextPropertyKey =
DependencyProperty.RegisterReadOnly("HasText",
typeof (bool), typeof (LabelTextBox), new PropertyMetadata());
/// <summary>True if the user has typed in text.</summary>
public static readonly DependencyProperty HasTextProperty = HasTextPropertyKey.DependencyProperty;
public bool HasText
{
get { return (bool)GetValue(HasTextProperty); }
private set { SetValue(HasTextPropertyKey, value); }
}
#endregion
#endregion
#region Construction
static LabelTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof (LabelTextBox), new FrameworkPropertyMetadata(typeof (LabelTextBox)));
}
#endregion
#region Event Handlers
protected override void OnTextChanged(TextChangedEventArgs e)
{
base.OnTextChanged(e);
HasText = Text.Length != 0;
}
#endregion
}
Style
<Style x:Key="{x:Type cc:LabelTextBox}" TargetType="{x:Type cc:LabelTextBox}">
<Setter Property="Background" Value="{StaticResource SearchTextBox_Background}" />
<Setter Property="BorderBrush" Value="{StaticResource SearchTextBox_Border}" />
<Setter Property="Foreground" Value="{StaticResource SearchTextBox_Foreground}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="LabelText" Value="Search" />
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="LabelTextColor" Value="{StaticResource SearchTextBox_LabelTextColor}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:LabelTextBox}">
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" Padding="2"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
>
<Grid x:Name="LayoutGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="PART_ContentHost" Grid.Column="0" />
<Label x:Name="LabelText" Grid.Column="0"
Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelTextColor}"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelText}"
Padding="2,0,0,0" FontStyle="Italic"
/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!--input triggers (mouse over && keyboard focused-->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SearchTextBox_BorderMouseOver}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SearchTextBox_BorderMouseOver}" />
</Trigger>
<!--Once the user has typed in search text-->
<Trigger Property="HasText" Value="True">
<!--Hide the label text-->
<Setter Property="Visibility" TargetName="LabelText" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--
Error display
-->
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right" Text=" *"
Foreground="Red"
FontWeight="Bold" FontSize="16"
ToolTip="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="placeholder"></AdornedElementPlaceholder>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="LightYellow"/>
</Trigger>
</Style.Triggers>
</Style>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这似乎有效。我所做的只是将您的代码复制到一个名为
LabelTextBox
的类中,并将您的Style
复制到Themes< 的
Generic.xaml
资源字典中。 /code> 文件夹放置在项目根目录(我将画笔颜色更改为 LightBlue、LightGray、Blue 等)This seems to be working. All I did was to copy your code in a class called
LabelTextBox
and yourStyle
in aGeneric.xaml
resource dictionary inThemes
folder placed at project root (I changed the brush colors to LightBlue, LightGray, Blue etc.)