想做一个带删除按钮的文本框,请问控件模板内的删除按钮怎样访问自定义文本框的Text属性?

wpf3d 2015-09-19 06:06:42


最终是想做一个像百度搜索框一样,没有输入文字时显示水印,且删除按钮不显示。
输入文字后,水印消失,点击文本框内的删除按钮时清空已输入文本。

水印问题暂不考虑。

用自定义控件时,控件模板内的删除按钮怎样访问到这个自定义控件(继承自TextBox)的Text属性呢?
...全文
408 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wpf3d 2015-11-04
  • 打赏
  • 举报
回复
发现问题:点击清除按钮清涂文本后再输入文字时,清除按钮并不是在Normal状态(也就是Opacity=0.4),而是MouseOver时的Opacity=1的状态。
wpf3d 2015-09-27
  • 打赏
  • 举报
回复
引用 6 楼 duanzi_peng 的回复:
给个样式吧。
多谢了,DataTrigger看着头疼,我没找资料,觉得未必支持SL,所以先用自己的VisualState方式将就着用了。就修改了一个部分,把水印文本由hard-coded,改成Dependency Property.
  • 打赏
  • 举报
回复 1
给个样式吧。

<!--搜索文本框样式-->
        <Style x:Key="ClearButtonTextBox" TargetType="{x:Type TextBox}">
            <Setter Property="MinWidth" Value="150"></Setter>
            <Setter Property="MinHeight" Value="20"></Setter>
            <Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
            <Setter Property="Margin" Value="5"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Border CornerRadius="0" BorderBrush="{DynamicResource txt_Focused_BorderBrush}" BorderThickness="1" Padding="0,0,5,0" 
Background="{TemplateBinding Background}">
                            <DockPanel LastChildFill="True">
                                <Button Width="16" Height="16" x:Name="PART_ContentHostClearButton"
 DockPanel.Dock="Right" HorizontalAlignment="Right">
                                    <Button.Template>
                                        <ControlTemplate TargetType="{x:Type Button}">
                                            <Border x:Name="PART_Border" CornerRadius="0,3,0,3" 
BorderBrush="Transparent" BorderThickness="0" Padding="2">
                                                <Path x:Name="PART_Path" Data="M6,6 L6,6 10,10 M10,6 L10,6 6,10"
 Fill="Gray" Stretch="Fill" Stroke="Gray" StrokeThickness="2" HorizontalAlignment="Center"
 VerticalAlignment="Center" />
                                            </Border>
                                            <ControlTemplate.Triggers>
                                                <Trigger Property="IsMouseOver" Value="True">
                                                    <Setter Property="Background" TargetName="PART_Border">
                                                        <Setter.Value>
                                                            <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                                                <GradientStop Color="Silver" Offset="0.0" />
                                                                <GradientStop Color="White" Offset="0.5" />
                                                                <GradientStop Color="Silver" Offset="0.0" />
                                                            </LinearGradientBrush>
                                                        </Setter.Value>
                                                    </Setter>
                                                    <Setter Property="Stroke" TargetName="PART_Path" 
Value="#FFBA3232" />
                                                </Trigger>
                                                <Trigger Property="IsPressed" Value="True">
                                                    <Setter Property="UIElement.Effect">
                                                        <Setter.Value>
                                                            <DropShadowEffect BlurRadius="10" 
Color="Black" Direction="0" Opacity="0.6" RenderingBias="Performance" ShadowDepth="0" />
                                                        </Setter.Value>
                                                    </Setter>
                                                </Trigger>
                                                <Trigger Property="IsFocused" Value="True" />
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </Button.Template>
                                </Button>
                                <!--内容-->
                                <ScrollViewer DockPanel.Dock="Left" Margin="2"  x:Name="PART_ContentHost" 
Background="{TemplateBinding Background}"/>
                            </DockPanel>
                        </Border>
                        <ControlTemplate.Triggers>
                            <!--当点击清除按钮后,清空文本框中的内容-->
                            <DataTrigger Binding="{Binding ElementName=PART_ContentHostClearButton,
Path=IsPressed}" Value="True">
                                <Setter Property="Text" Value="{x:Null}"/>
                            </DataTrigger>
                            <!--当文本框中有内容的时候显示清除按钮-->
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self},
Path=Text.Length}" Value="0"/>
                                    <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self},
Path=IsFocused}" Value="False"/>

                                </MultiDataTrigger.Conditions>
                                <MultiDataTrigger.Setters>
                                    <Setter TargetName="PART_ContentHostClearButton" Property="Visibility"
 Value="Collapsed" />
                                    <Setter TargetName="PART_ContentHost" Property="Background">
                                        <Setter.Value>
                                            <VisualBrush Opacity="1" Stretch="None">
                                                <VisualBrush.Visual>
                                                    <TextBlock Text="Enter key word" FontSize="12" 
HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{StaticResource filterTextBox_Foreground}"/>
                                                </VisualBrush.Visual>
                                            </VisualBrush>
                                        </Setter.Value>
                                    </Setter>
                                </MultiDataTrigger.Setters>
                            </MultiDataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
wpf3d 2015-09-25
  • 打赏
  • 举报
回复

引用 2 楼 hbu_pig 的回复:
自定义控件。。
外面一个border,里面一个textbox,右侧一个删除的图标或者path啥的
在OnApplyTemplate方法可以找到ui的控件




谢谢,大概做了下。用VisualState来控制清除按钮的显示/隐藏。对DataTrigger不了解。
整体感觉还是很粗糙。希望指正。

自定义控件
Generic.xaml ResourceDictionary中的ClearButton

<Style TargetType="local:ClearButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ClearButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ButtonPath" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="00:00:01" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Path x:Name="ButtonPath" Data="M0,0 L0,0 2,2 M2,0 L2,0 0,2" Stretch="Fill" Stroke="Black" StrokeThickness="2" Opacity="0.4" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


Generic.xaml ResourceDictionary中的ClearTextBox
去掉了默认控件中验证相关的东西,其他都保留了。然后用DockPanel来对ScrollViewer和ClearButton进行了布局。

<Style TargetType="local:ClearTextBox">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>

<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ClearTextBox">
<Grid x:Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF99C1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="MouseOverBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement"/>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ReadOnlyVisualElement"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ClearButtonStates">
<VisualState x:Name="ButtonCollapsed" />
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ClearTextButton">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>

<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="WatermarkText">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="1" Opacity="1">
<Grid>
<Border x:Name="ReadOnlyVisualElement" Background="#5EC9C9C9" Opacity="0"/>
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<Grid>
<TextBlock x:Name="WatermarkText" Text="Input some text" Opacity="0.5" VerticalAlignment="Center" HorizontalAlignment="Center" />
<toolkit:DockPanel LastChildFill="True">
<local:ClearButton x:Name="ClearTextButton" toolkit:DockPanel.Dock="Right" Background="Transparent" Width="16" Height="16" Visibility="Collapsed" />
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
</toolkit:DockPanel>
</Grid>
</Border>
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}" Background="#A5F7F7F7" IsHitTestVisible="False" Opacity="0"/>
<Border x:Name="FocusVisualElement" IsHitTestVisible="False" Margin="1" Opacity="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


ClearTextBoxc.cs

public class ClearTextBox : TextBox
{
public ClearTextBox()
{
this.DefaultStyleKey = typeof(ClearTextBox);

this.TextChanged += (s, e) => { ChangeClearButtonState(); };
}

protected virtual void ChangeClearButtonState()
{
VisualStateManager.GoToState(this, String.IsNullOrEmpty(this.Text) ? "ButtonCollapsed" : "ButtonVisible", false);
}


public override void OnApplyTemplate()
{
base.OnApplyTemplate();

ClearButton btn = base.GetTemplateChild("ClearTextButton") as ClearButton;
if(btn != null)
btn.Click += (s, e) => this.Text = string.Empty;

}
}


不太理解的问题是:
1、<local:ClearButton x:Name="ClearTextButton" toolkit:DockPanel.Dock="Right" Background="Transparent" Width="16" Height="16" Visibility="Collapsed" />
在ClearTextBox引用ClearButton时,必须指定背景,不然只有点击X部分时才会触发Click事件。这方面有什么解释吗?
2、控件模板中水印部分有没有更好的实现?
3、没有后台代码,只用DataTrigger怎么实现?
  • 打赏
  • 举报
回复
引用 3 楼 wpf3d 的回复:
[quote=引用 1 楼 duanzi_peng 的回复:] 修改控件模板就行了。 http://www.luacloud.com/2011/wpf-textbox-clearbutton-watermark.html
大概看了下示例代码,WPF可以用<DockPanel LastChildFill="True">定位文本框内的清除按钮, 那silverlight有什么类似的方式放置清除按钮呢?固定清除按钮大小又显得不够灵活。[/quote] -》 silverlight 也有DockPanel。 固定清楚按钮不够灵活? 那怎么样才能显得灵活,实在想不到更好的方式了。
wpf3d 2015-09-24
  • 打赏
  • 举报
回复
引用 1 楼 duanzi_peng 的回复:
修改控件模板就行了。 http://www.luacloud.com/2011/wpf-textbox-clearbutton-watermark.html
大概看了下示例代码,WPF可以用<DockPanel LastChildFill="True">定位文本框内的清除按钮, 那silverlight有什么类似的方式放置清除按钮呢?固定清除按钮大小又显得不够灵活。
欢乐的小猪 2015-09-21
  • 打赏
  • 举报
回复
自定义控件。。 外面一个border,里面一个textbox,右侧一个删除的图标或者path啥的 在OnApplyTemplate方法可以找到ui的控件
  • 打赏
  • 举报
回复

8,756

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧