I have re-styled a textbox using a control template. The styling works well but I cannot now get the text value from the textbox programatically after it has been changed in the textbox.
Here is how I use the style:
<TextBox
x:Name="KernTextBox"
Style="{StaticResource MediumTextBoxStyle}"
TextWrapping="Wrap"
MinLines="1"
MaxLines="5"
VerticalScrollBarVisibility="Auto"
TextChanged="TextChanged"
/>
Here is what does not work.
get { return KernTextBox.Text; }
Here is the style:
<Style x:Key="MediumTextBoxStyle" TargetType="TextBox">
<Setter Property="FontSize" Value="18" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver" />
<VisualState x:Name="ReadOnly">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonRectangle"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource ForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonText"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource BackgroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonText"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource ForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonText"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource ForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonRectangle"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource ForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonText"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource BackgroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonText"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource ForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ButtonText"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{StaticResource ForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked" />
<VisualState x:Name="Unchecked"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle
x:Name="ButtonRectangle"
Stroke="Transparent"
UseLayoutRounding="False"
Fill="{StaticResource BackgroundBrush}">
</Rectangle>
<TextBox
x:Name="ButtonText"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
FontSize="{TemplateBinding FontSize}"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Margin="2 0"
TextWrapping="{TemplateBinding TextWrapping}"
MinLines="{TemplateBinding MinLines}"
MaxLines="{TemplateBinding MaxLines}"
VerticalScrollBarVisibility="{TemplateBinding VerticalScrollBarVisibility}"
Padding="{TemplateBinding Padding}"
Foreground="{StaticResource ForegroundBrush}"
Background="{StaticResource BackgroundBrush}"
>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
EDIT:
Final working style:
<Style
x:Key="TextBoxStyle"
TargetType="{x:Type TextBox}">
<Setter
Property="Foreground"
Value="{StaticResource ForegroundBrush}" />
<Setter
Property="FontSize"
Value="18" />
<Setter
Property="CaretBrush"
Value="{StaticResource ForegroundBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border
Name="Border"
Background="{StaticResource BackgroundBrush}"
BorderBrush="{StaticResource ForegroundBrush}"
BorderThickness="1" >
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ForegroundBrush}"/>
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource BackgroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource BackgroundBrush}"/>
</Trigger>
<Trigger Property="IsReadOnly" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ForegroundBrush}"/>
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource BackgroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource BackgroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Is there a reason why you place a textbox inside a textbox? Checkout the original style and template of a textbox and modify it from there. My guess is, the textbox uses a TextBoxView(hidden in the Scrollviewer) internally and the Text property is not bound via TemplateBinding, but calculated between these internal classes. So maybe thats the reason why you can’t bind your text property to the textbox text in your control template.