Click here to Skip to main content
15,897,226 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am fairly new to WPF and I am slowly collecting tips and tricks from across the web to put my project together. I am currently having trouble getting all my ducks in a row for data validation using an AdornedElementPlaceholder.

in my resource file I have

<Style TargetType="{x:Type TextBox}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="True">
                        <TextBlock DockPanel.Dock="Right" 
                        Foreground="Orange"
                        FontSize="12pt" 
                        ToolTip="{Binding ElementName=MyAdorner, 
                                          Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">***
                        </TextBlock>
                        <Border BorderBrush="Red" BorderThickness="2">
                            <AdornedElementPlaceholder Name="MyAdorner"/>
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                 <Setter Property="Background" Value="MistyRose"/>
            </Trigger>
        </Style.Triggers>
    </Style>

and this is the textbox I'm working with currently to make things work
<TextBox Grid.Column="2" Height="23" Name="txtRefreshTime" Width="60" MaxLength="3">
    <TextBox.Text>
        <Binding FallbackValue="59" RelativeSource="{RelativeSource Self}" Path="Text">
            <Binding.ValidationRules>
                <val:StringRangeValidationRule
                    MinimumLength="1"
                    ErrorMessage="Must have a numeric value."/>
                <val:NumericInputValidationRule
                    IsAType="intType"
                    ErrorMessage="Must be a number of seconds."/>
                <val:NumericRangeValidationRule
                    MinimumValue="5"
                    MaximumValue="900"
                    ErrorMessage="Value must be between 5 and 900 seconds (15 minutes)."/>
            </Binding.ValidationRules>
            </Binding>
    </TextBox.Text>
</TextBox>

Everything works exactly how I want it to EXCEPT once the validation takes place and an error is found I can't click and set focus on the textbox. I can tab to it but I can't click on it. I downloaded an example from here and the code doesn't show anything different and it works just fine. Any ideas on what I have wrong or a way to fix the problem?


I also have used this piece into the resource file as a replacement for the above. It is similar to the above bit of style and it also 'almost' works, but the tooltip doesn't show.

<Style TargetType="{x:Type TextBlock}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <AdornedElementPlaceholder Name="controlWithError" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="Background" Value="MistyRose"/>
            <Setter Property="ToolTip"
            Value="{Binding RelativeSource={RelativeSource Self},
            Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>


And as requested some of the validation code

public class StringRangeValidationRule : ValidationRule
    {
        private int _minimumLength = -1;
        private int _maximumLength = -1;
        private string _errorMessage;

        public int MinimumLength
        {
            get { return _minimumLength; }
            set { _minimumLength = value; }
        }

        public int MaximumLength
        {
            get { return _maximumLength; }
            set { _maximumLength = value; }
        }

        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; }
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            ValidationResult result = new ValidationResult(true, null);
            string inputString = (value ?? string.Empty).ToString();
            if (inputString.Length < this.MinimumLength ||
                   (this.MaximumLength > 0 &&
                    inputString.Length > this.MaximumLength))
            {
                result = new ValidationResult(false, this.ErrorMessage);
            }

            return result;
        }
    }
Posted
Updated 22-Jul-13 3:05am
v3
Comments
aliwpf 22-Jul-13 3:05am    
Hi dude. is it possible write your validation class?
bowlturner 22-Jul-13 9:01am    
I can but that part appears to be working correctly. The only problem I have with this one is I can't actually click on the textbox after validation has occurred.

1 solution

I found this gave me the functionality that I need, but I still don't know why the other code didn't work.

<style targettype="{x:Type TextBox}">
        <style.triggers>
           <trigger property="Validation.HasError" value="True">
               <setter property="Background" value="MistyRose" />
               <setter property="ToolTip" value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)[0].ErrorContent}" />
           </trigger>
       </style.triggers>
   </style>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900