【问题标题】:WPF customized TextBoxWPF自定义文本框
【发布时间】:2013-12-17 00:05:37
【问题描述】:

我有一个名为“txtAddress”的自定义文本框,其中包含Image 和TextBox。
我需要能够访问它的内容:txtAddress.TexttxtAddress.Image
我已经将inner textBox.text 与Template.Text 和inner rect.Fill 与Template.Background 绑定(我现在使用矩形,我将其更改为图像)

当我运行程序并编辑文本框时,一切看起来都在正常工作,文本也在发生变化,但是当我从代码中使用它时,txtAddress.Text 仍然是“我的电脑”,这是 初始值文本框的强>。 我知道,因为我没有将<ContentPresenter> 放在样式中的某个位置,但是我应该将控件(图像,文本框)放在哪里,例如在 listView 中有<DataTemplate> 我们添加控件的地方

TxtAddress 样式:

<Style x:Key="TextBoxAddressStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
        <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="AllowDrop" Value="true"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Grid HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" Width="Auto">
                        <Rectangle Height="Auto" Stroke="{TemplateBinding Foreground}" VerticalAlignment="Stretch" RadiusY="11" RadiusX="11" Margin="0" Fill="{TemplateBinding OpacityMask}"/>
                        <!--<ContentPresenter Height="Auto" Margin="31,2,7.458,2"/>-->
                        <TextBox x:Name="TxtAddress" Height="Auto" Margin="31,2,7.458,2" VerticalAlignment="Stretch" MaxLines="1" Text="{TemplateBinding Text}" AcceptsTab="True" Style="{DynamicResource TextBoxStyle2}" SelectionBrush="#C859003D" FontSize="{TemplateBinding FontSize}" AcceptsReturn="False"/>
                        <Rectangle Fill="#5AFFFFFF" HorizontalAlignment="Stretch" Height="6.375" Margin="6,2.25,6,0" RadiusY="6" RadiusX="6" Stroke="{x:Null}" VerticalAlignment="Top" Width="Auto" d:IsLocked="True"/>
                        <Rectangle x:Name="ImgAddress" Fill="{TemplateBinding Background}" HorizontalAlignment="Left" Height="24" Margin="7,1,0,0" RadiusY="0" RadiusX="0" VerticalAlignment="Top" Width="24" StrokeThickness="0">
                            <Rectangle.Stroke>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="Black" Offset="1"/>
                                    <GradientStop Color="White"/>
                                </LinearGradientBrush>
                            </Rectangle.Stroke>
                        </Rectangle>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
                    <Condition Property="IsSelectionActive" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
            </MultiTrigger>
        </Style.Triggers>
    </Style>

内部文本框样式:

<Style x:Key="TextBoxStyle2" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
        <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="AllowDrop" Value="true"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" FontSize="13.333" PanningMode="HorizontalOnly"/>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
                    <Condition Property="IsSelectionActive" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
            </MultiTrigger>
        </Style.Triggers>
    </Style>

文本地址:

 <TextBox x:Name="txtAddress" Margin="34,5,32,0" TextWrapping="Wrap" Text="My Computer" Style="{DynamicResource TextBoxAddressStyle}" Height="25" VerticalAlignment="Top" FontWeight="Bold" MinHeight="25" MaxHeight="25">
            <TextBox.Background>
                <ImageBrush ImageSource="BtnImg/computer.png" Stretch="None"/>
            </TextBox.Background>
            <TextBox.Foreground>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF779198" Offset="0.1"/>
                    <GradientStop Color="#FF789399" Offset="0.93"/>
                    <GradientStop Color="#FFBFD3D7" Offset="0.513"/>
                    <GradientStop Color="#FF343E41" Offset="1"/>
                    <GradientStop Color="#FF5C6E73"/>
                </LinearGradientBrush>
            </TextBox.Foreground>
            <TextBox.OpacityMask>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF94B5BD" Offset="0.1"/>
                    <GradientStop Color="#FF94B5BD" Offset="0.93"/>
                    <GradientStop Color="#FFE7FBFF" Offset="0.513"/>
                    <GradientStop Color="#FF7B9399" Offset="1"/>
                    <GradientStop Color="#FF7B9399"/>
                </LinearGradientBrush>
            </TextBox.OpacityMask>
        </TextBox>

提前致谢。

【问题讨论】:

  • 你为什么要在代码中使用它?你在使用 MVVM 吗?绑定到您的 ViewModel 是否正常工作?
  • 绑定正常工作“一半”,我的意思是当我运行项目时,内部文本在图形中发生变化而不是在其内容中,所以如果我将文本更改为“随便”,当我使用它时编码它仍然是“我的电脑”

标签: wpf xaml textbox


【解决方案1】:

您在模板中放置了一个TextBox,用于另一个TextBox。

视觉树将如下所示:

TextBox
   Grid
      Rectangle 
      TextBox
      Rectangle 
      Rectangle

这首先是不理想的,但如果你想保留这样的东西,只需确保通过Two Way、UpdateSourceTrigger=PropertyChanged 数据绑定将内部 TextBox 的 Text 属性绑定到外部属性所以:

<TextBox x:Name="TxtAddress" Text="{Binding Text, 
                                            Mode=TwoWay, 
                                            UpdateSourceTrigger=PropertyChanged,  
                                            RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" ... />

除此之外,我已经多次提到您不应该在 WPF 的过程代码中操作 UI 元素。

相反,创建一个合适的 ViewModel 来存储您的数据:

public class MyViewModel
{
    public string Text {get;set;}
}

然后使用 DataBinding 将您的 TextBox 绑定到该数据:

<TextBox Text="{Binding Text}"/>

当您需要检索值时,请从 VM 而非 UI 中检索值。

【讨论】:

  • 您认为这个文本框的理想选择是什么?我应该创建包含图像和文本框的用户控件吗?
  • @MurHaf 要么,要么从 Default one 开始创建您的 TextBox 模板,其中已经包含相关的 Template Parts
  • 我做了什么,我编辑了一个副本然后我删除了 chrome 然后我添加了控件然后我将 innerText 绑定到模板文本
  • 你能告诉我如何使用 VM 来做吗,我害怕创建不必要的代码,我正在尝试像本教程 codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial 那样做,但我可以在我的情况下看到只需要1个静态ExploreAddress(文本,图像)而不是ExploreAddress的集合
  • @MurHaf 这是它自己的一个单独问题,你不觉得吗?发布一个新问题,让我知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-03
相关资源
最近更新 更多