Validated Textbox in a UserControl

3.1k views Asked by At

I have created a UserControl - a Labeled TextBox which is working pretty well, except for the validation template. When there's an error the validation control template shows up but it fills the whole space including the Label. I only want it to be as big as the TextBox. How to fix this?

Here's the xaml:

<UserControl x:Class="Infrastructure.CustomControls.LabelTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Name="LTB">

    <Grid HorizontalAlignment="{Binding}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <TextBlock x:Name="tbl" 
                   FontFamily="{Binding}" 
                   FontSize="{Binding}" 
                   Text="{Binding ElementName=LTB, Path=LabelText}" 
                   Height="{Binding ElementName=LTB, Path=LabelHeight}" 
                   Width="{Binding ElementName=LTB, Path=LabelWidth}" 
                   VerticalAlignment="Center"/>
        <TextBox x:Name="tbx" 
                 Grid.Column="1" 
                 FontFamily="{Binding}" 
                 FontSize="{Binding}" 
                 IsReadOnly="{Binding ElementName=LTB, Path=IsReadOnly}" 
                 MaxLength="{Binding ElementName=LTB, Path=TextMaxLength}" 
                 Text="{Binding ElementName=LTB, Path=Text}" 
                 Height="{Binding ElementName=LTB, Path=TextHeight}"
                 Width="{Binding ElementName=LTB, Path=TextWidth}" 
                 VerticalAlignment="Center">
            <Validation.ErrorTemplate>
                <ControlTemplate>
                    <DockPanel LastChildFill="True" 
                               ToolTip="{Binding ElementName=aep, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                        <TextBlock DockPanel.Dock="Right" 
                                   Foreground="Red" 
                                   FontSize="14pt" Text="*" 
                                   Margin="-15,0,0,0" 
                                   FontWeight="Bold"/>
                        <Border BorderBrush="Red" BorderThickness="1">
                            <AdornedElementPlaceholder Name="aep"/>
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Validation.ErrorTemplate>
        </TextBox>
    </Grid>
</UserControl>
2

There are 2 answers

0
sysboard On BEST ANSWER

Thanks for the response, it helped me figure out where the problem is. And for that i vote it as useful.

What i did was programmatically query the UserControl validation for errors in the TextBoxChangedEvent and set the validation error manually (http://wpftutorial.net/ValidationErrorByCode.html) for the TextBox.

0
Adi Lester On

The reason why this happens is that you're implementing IDataErrorInfo in your view and not your UserControl. This causes the default WPF red border to appear for the entire usercontrol.

To get your defined error template to appear, you'll need to implement IDataErrorInfo in your usercontrol and add ValidatesOnDataErrors=True to your binding expression.

If you'd like to keep the IDataErrorInfo logic in your view and not in your UserControl (which is pretty reasonable), you'll need to define a validation template for the user control in the view:

<Window>
    <local:UserControl>
        <Validation.ErrorTemplate>
            <ControlTemplate>
                ...
            </ControlTemplate>
        </Validation.ErrorTemplate>
    </local:UserControl>
</Window>

To get it to only show the border for the TextBox, you can play with the border's width using a converter that'll take the entire usercontrol's width as a parameter and return the width of the textbox; possibly something like this:

<Border BorderBrush="Red" BorderThickness="1" Width="{Binding ElementName=ph, Path=ActualWidth, Converter={StaticResource myConverter}}">
    <AdornedElementPlaceholder Name="ph" />
</Border>