0

I am continuing my learning with a small project in C# WPF. My current situation is I want to make a border of a TextBox change when an error occurs on a user input eg can not parse their input into a decimal number.

After some reading up I have used a control template, the XAML is below, but when I run the project the TextBox using the control template (textBox1) does not show any text and I can not see what I have done wrong. Can any one help please?

Also I am triggering the change with a IsMouseOver property just while I learn, but in my project I want to trigger off an error property so in my mind I would need to add to my TextBox control a property IsError as a bool and behind my code when I test the user input and it fails the Parse I would set the TextBox property IsError to true and that would trigger the ControlTemplate change. However, can this be done or is there a more standed way to do this? Thanks.

XAML of ControlTemplate

<Window x:Class="TestContentStyle.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="StyleTriggersSample" Height="100" Width="300">
<Window.Resources>
    <!--A ControlTemplate for textbox including error-->
    <ControlTemplate TargetType ="TextBox" x:Key="OnError">
        <TextBox   Name="TextBox"
                    FontSize="28" 
                    HorizontalAlignment="Center" 
                    VerticalAlignment="Center" 
                    BorderBrush="Silver"
                    BorderThickness="1"
                    Height="50"
                    Width="120"/>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver"
                            Value="True">
                        <Setter TargetName="TextBox"
                            Property="BorderThickness"
                            Value="5" />
                    </Trigger>
                </ControlTemplate.Triggers>
    </ControlTemplate>



</Window.Resources>

    <Grid>

    <TextBox Text="Tesing1" Margin="146,23,0,0" Name="textBox1" Template="{StaticResource OnError}" />
    <TextBox Text="Testing2" Height="23" HorizontalAlignment="Left" Margin="12,23,0,0" Name="Test1"  VerticalAlignment="Top" Width="120" />
</Grid>

Gromy
  • 258
  • 1
  • 15
Ian W
  • 385
  • 2
  • 10
  • 30
  • You can accomplish this using built in validation that is shipped with WPF – Kcvin Sep 10 '15 at 13:55
  • The validation methods examples I saw all used viewmodels which are to be frank abit advanced for me – Ian W Sep 10 '15 at 13:57
  • You're using a `TextBox` inside the `ControlTemplate` of a `TextBox`, and that doesn't make any sense. – almulo Sep 10 '15 at 14:00

1 Answers1

2

First of all, templates define how a control is rendered. They define their whole look.

You're telling the TextBox to render itself with another different TextBox inside. That means that the TextBox you're seeing in your app is not actually the one you've defined inside your Grid, with the "Testing1" text, but the one you've defined inside the ControlTemplate that has no text set.

But other than that, you don't need a whole new ControlTemplate for this. You just need a Style:

<Window.Resources>
    <Style TargetType="TextBox" x:Key="OnError">
        <Setter Property="FontSize" Value="28" />
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="BorderBrush" Value="Silver" />
        <Setter Property="Height" Value="50" />
        <Setter Property="Width" Value="120" />
        <Style.Triggers>
            <Trigger Property="IsMouseOver"
                     Value="True">
                <Setter Property="BorderThickness"
                        Value="5" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid>
    <TextBox Text="Tesing1" Margin="146,23,0,0" Name="textBox1" Style="{StaticResource OnError}" />
    <TextBox Text="Testing2" Height="23" HorizontalAlignment="Left" Margin="12,23,0,0" Name="Test1"  VerticalAlignment="Top" Width="120" />
</Grid>

Also, in WPF you don't usually use Margin to create a layout :P Instead, you should add ColumnDefinitions and RowDefinitions to your Grid, and use the Grid.Row and Grid.Column attached properties on your TextBoxes to specify their location in your view.

almulo
  • 4,918
  • 1
  • 20
  • 29
  • Thanks, funny I started this using a style but thought the ControlTemplate was correct :-( As for the layout, yes I do know the form but this was a temporary project just for testing this out, so I did not bother, but I will bear it in mind to tidy up before posting. BTW do you know if I can define my own property to the TextBox as I describe for triggering purposes? – Ian W Sep 10 '15 at 14:33
  • You could extend the `TextBox` class to create your custom textbox, and add your property there. Or you could use attached properties, which are a bit too advanced for your right now, probably. – almulo Sep 10 '15 at 14:43
  • 1
    Yep the style was good, and thank you for the advice about extending the TextBox class and understanding the limitations us learners have, not all posters get we are learning to walk on this journey and not ready to run with you guys...A new learning project starts extending TextBox class thanks! :-) – Ian W Sep 10 '15 at 14:52
  • You're welcome! Just a hint, though ;) If you plan on using your new Property in a Trigger, you'll have to make sure it notifies its changes either through the PropertyChanged event (which means your custom TextBox must implement the IPropertyChanged interface)... Or making your property a Dependency Property instead of just a regular one. Dependency Properties are more complex but have a lot of benefits, so it might be worth to check. – almulo Sep 10 '15 at 15:14
  • Thanks for the extra advice Going For Dependency Properties might as well stretch myself :-) – Ian W Sep 10 '15 at 15:22
  • That's the spirit! Once you understand Dependency Properties, Attached Properties become quite straight-forward since they're very similar and based on the same principles. – almulo Sep 10 '15 at 15:28