0

I made a custom made style for a textbox using PATH. The box looks exactly how i wanted it but when i write any text in it, nothing seems to appear. It would seem that something inside my style is either blocking it or i need to add something for the content to appear. But im not sure what exactly, does anyone have any insight on what i could do to make the text appear inside the custom made box?

<Style x:Key="AppearingTextbox" TargetType="{x:Type TextBox}">
  <Setter Property="Cursor" Value="Arrow"/>
  <Setter Property="Foreground" Value="#3E82C4"/>
  <Setter Property="Background" Value="#0F1C2B"/>
  <Setter Property="Opacity" Value="0"/>
  <Setter Property="IsReadOnly" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TextBox}">
        <StackPanel>
          <Path Data="M0 0 30 0 50 -10 70 0 100 0 100 30 0 30z" Fill="#0F1C2B"/>
        </StackPanel>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Style.Triggers>
    <DataTrigger Binding="{Binding ElementName=Ikona, Path=IsMouseOver}" Value="True">
      <DataTrigger.EnterActions>
        <BeginStoryboard >
          <Storyboard TargetProperty="Opacity" Duration="00:00:00.3" AutoReverse="False">
            <DoubleAnimation From="0" To="1" Duration="00:00:00.3"/>
          </Storyboard>
        </BeginStoryboard>
      </DataTrigger.EnterActions>
      <DataTrigger.ExitActions>
        <BeginStoryboard >
          <Storyboard TargetProperty="Opacity" Duration="00:00:00.3" AutoReverse="False">
            <DoubleAnimation From="1" To="0" Duration="00:00:00.3"/>
          </Storyboard>
        </BeginStoryboard>
      </DataTrigger.ExitActions>
    </DataTrigger>
  </Style.Triggers>
</Style>

That is applied to this TextBox:

<TextBox Style="{DynamicResource AppearingTextbox}" Height="30" Width="100" FontSize="10" Margin="0,480,0,0">
        Some text
</TextBox>

Thanks a bunch people i managed to get it working. I couldnt put it inside of a Border tag because border tag accepts only 1 child element. Instead I used Grid. Grid is also good because in documentation I read somewhere that it allows stacking elements on top of each other. This is what I did for anyone that stumbles on this in the future.

In the <ControlTemplate> tag I did the following:

<ControlTemplate TargetType="{x:Type TextBox}">
  <Grid>
    <Path Data="M0 0 30 0 50 -10 70 0 100 0 100 30 0 30z" Fill="#0F1C2B"/>
    <ScrollViewer Margin="0" x:Name="PART_ContentHost" />
  </Grid>
</ControlTemplate>

Which immediately made the text appear inside the box I made. A little styling made the text right where I wanted it but that's about it.
Thanks a lot people and consider this solved :)

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Ivan Horvatin
  • 217
  • 1
  • 2
  • 14
  • So when you add your text as `Content` of the TextBox, where in your template is your `Content` handled? Compare yours to a default, I'd bet you spot your folly pretty quick. :) – Chris W. Dec 30 '15 at 19:45

2 Answers2

2

TextBox template requires named part

<ScrollViewer x:Name="PART_ContentHost" />

to host its content and provide edit functionality

From MSDN

A visual element that can contain a FrameworkElement. The text of the TextBox is displayed in this element.

Edit

<ControlTemplate TargetType="{x:Type TextBox}">
   <Grid>
      <Path Data="M0 0 30 0 50 -10 70 0 100 0 100 30 0 30z" Fill="#0F1C2B"/>
      <ScrollViewer x:Name="PART_ContentHost"/>
   </Grid>
</ControlTemplate>
dkozl
  • 32,814
  • 8
  • 87
  • 89
  • Was trying to teach the man to fish, but +1 since it's correct. – Chris W. Dec 30 '15 at 20:00
  • But where do i put it? When i try to add it inside the Control Template if i dont have i get the 'The property Visual Tree is set more then once.' – Ivan Horvatin Dec 30 '15 at 20:01
  • @ChrisW. I read a bit on the net and found out that that particular part of code needs to be in there. But wherever i try to put it, i get some errors. I even tried adding both in a Stack Panel, but nothing happens...im certanly missing something small.. – Ivan Horvatin Dec 30 '15 at 20:03
  • @IvanHorvatin you need to put in your `ControlTemplate` where you want input/text to appear and it must be named exactly like that. – dkozl Dec 30 '15 at 20:07
1

MSDN gives an example of TextBox style and enumerates named parts. For TextBox it is PART_ContentHost which displays its content. In default template it is ScrollViewer:

<ScrollViewer Margin="0" x:Name="PART_ContentHost" />

If you add it to StackPanel the elements will display consecutive but you need to display text ahead from your Path. Then change StackPanel to Grid.

<Grid>
    <Path Data="M0 0 30 0 50 -10 70 0 100 0 100 30 0 30z" Fill="#0F1C2B"/>
    <ScrollViewer Margin="0" x:Name="PART_ContentHost" />
</Grid>

Next we need to align elements with each other, then you can add VerticalAlignment and HorizontalAlignment.

<Grid>
    <Path VerticalAlignment="Center" HorizontalAlignment="Center" Data="M0 0 30 0 50 -10 70 0 100 0 100 30 0 30z" Fill="#0F1C2B"/>
    <ScrollViewer VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" x:Name="PART_ContentHost"  />
</Grid>

Finally you have another one issue. By default text color is black. You can change it by override Foreground property:

<Setter Property="Foreground" Value="White" />

Full style will be looks like this:

<Style x:Key="AppearingTextbox" TargetType="{x:Type TextBox}">
    <Setter Property="Cursor" Value="Arrow"/>
    <Setter Property="Foreground" Value="#3E82C4"/>
    <Setter Property="Background" Value="#0F1C2B"/>
    <Setter Property="Opacity" Value="0"/>
    <Setter Property="IsReadOnly" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBoxBase}">
                <Grid>
                    <Path VerticalAlignment="Center" HorizontalAlignment="Center" Data="M0 0 30 0 50 -10 70 0 100 0 100 30 0 30z" Fill="#0F1C2B"/>
                    <ScrollViewer VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" x:Name="PART_ContentHost" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding ElementName=Ikona, Path=IsMouseOver}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard >
                    <Storyboard TargetProperty="Opacity" Duration="00:00:00.3" AutoReverse="False">
                        <DoubleAnimation From="0" To="1" Duration="00:00:00.3"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <BeginStoryboard >
                    <Storyboard TargetProperty="Opacity" Duration="00:00:00.3" AutoReverse="False">
                        <DoubleAnimation From="1" To="0" Duration="00:00:00.3"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
  • Im gonna choose your answer because its very extensive and adds a lot to the answer – Ivan Horvatin Dec 30 '15 at 20:25
  • NP I just updated my question to make more detailed guide for each part of problem. – Vadim Martynov Dec 30 '15 at 20:26
  • Just one question, what does SnapsToDevicePixels do, or OverridesDefaultStyle. I choose TexBox because i could style it with path. But dont want any input in it so i used IsReadOnly part – Ivan Horvatin Dec 30 '15 at 20:28
  • SnapsToDevicePixels prevents blurring of pixels. It determines whether rendering for this element should use device-specific pixel settings during rendering. Also I updated my answer because this properties is already set in base style. – Vadim Martynov Dec 30 '15 at 20:31
  • When is that suppose to be used then? And thanks a lot :) – Ivan Horvatin Dec 30 '15 at 20:36
  • Well it's only my experience and not a rule but in the cases with very small elements if I can see blurring artifacts I'll set this property to true. See also http://stackoverflow.com/questions/2399731/when-should-i-use-snapstodevicepixels-in-wpf-4-0 – Vadim Martynov Dec 30 '15 at 20:41