WPF 自定义文本框 [英] WPF customized TextBox
问题描述
我有一个名为txtAddress"的自定义文本框,其中包含 Image
和 TextBox
.
我需要能够访问它的内容:txtAddress.Text
txtAddress.Image
我已将 inner textBox.text
与 Template.Text
和 inner rect.Fill
与 Template.Background
绑定> (我现在用的是矩形,我会改成图片)
I have a customized TextBox named "txtAddress" which contains Image
and TextBox
.
I need to be able to access its contents : txtAddress.Text
txtAddress.Image
I've Bound the inner textBox.text
with the Template.Text
and inner rect.Fill
with Template.Background
(I'm using rectangular now, i will change it to image)
当我运行程序并编辑文本框时,一切看起来都在正常工作并且文本正在发生变化,但是当我从代码中使用它时 txtAddress.Text
仍然是我的电脑",它是文本框的初始值.我知道这是因为我没有将
放在样式中的某处,但是我应该将控件(图像,文本框)放在哪里,就像在 listView 中有
我们在其中添加控件
when I run the program and edit the textBox everything looks like its working and the text is changing, but when i use it from the code txtAddress.Text
is still "my computer" which is the initial value of the TextBox.
I know that because i didn't put <ContentPresenter>
somewhere in the style but where should i put the controls(image,textbox), like in listView there is <DataTemplate>
where we add the controls
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>
提前致谢.
推荐答案
您将一个 TextBox
放置在另一个 TextBox
的模板中.
You're placing a TextBox
inside the Template for another TextBox
.
视觉树看起来像这样:
TextBox
Grid
Rectangle
TextBox
Rectangle
Rectangle
这首先并不理想,但如果您想保留这样的东西,只需确保通过 两种方式
, UpdateSourceTrigger=PropertyChanged
像这样的数据绑定:
Which is not ideal in the first place, but if you want to keep things like that, just make sure you bind the inner TextBox's Text
property to the outer one, via Two Way
, UpdateSourceTrigger=PropertyChanged
Data Binding like so:
<TextBox x:Name="TxtAddress" Text="{Binding Text,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" ... />
<小时>
除此之外,我已经多次提到您不应该在 WPF 的程序代码中操作 UI 元素.
In addition to all this, I already mentioned several times that you're NOT supposed to be manipulating UI elements in procedural code in WPF.
相反,创建一个合适的 ViewModel 来存储您的数据:
Instead, create a proper ViewModel to store your data:
public class MyViewModel
{
public string Text {get;set;}
}
然后使用 DataBinding 将您的 TextBox 绑定到该数据:
then use DataBinding to bind your TextBox to that data:
<TextBox Text="{Binding Text}"/>
每当您需要检索值时,请从 VM 中检索值,而不是从 UI 中检索.
And whenever you need to retrieve the value, retrieve the value from the VM, NOT the UI.
这篇关于WPF 自定义文本框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!