Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding Validation.ErrorTemplate in UserControl

I have a user control that has a textbox where its text property is bound to a dependency property called SelectedValue. When the user enters text, that value is validated against another DP called ItemsSource to see if it in there. If not, I throws an error. Everything works - the TB in the UC has the default red box around it when there is an error.

But I would like the user to be able to specify a ControlTemplate in XAML when creating an instance of the UC. So I thought I could create another DP of type ControlTemplate and they could bind to. This seems to work but how do I actually implement that in XAML? If it do something like:

Validation.ErrorTemplate="{Binding ValidationTemplate}"

it throws an error saying "'ErrorTemplate' property cannot be data-bound.". Below are the relevant parts of the code:

<Canvas DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
    ....
    <TextBox x:Name="ValueTextBox"
             TextWrapping="NoWrap" 
             GotFocus="_ValueTextBox_GotFocus"
             Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualWidth}"
             Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualHeight}"
       ----->Validation.ErrorTemplate="{Binding ValidationTemplate}"<-----
             >

        <TextBox.Resources>
            <CollectionViewSource x:Key="UniqueNamesList" Source="{Binding ItemsSource}" />
        </TextBox.Resources>

        <TextBox.Text>
            <Binding Path="SelectedValue" >
                <Binding.ValidationRules>
                    <l:InListValidator ValidationStep="RawProposedValue" 
                                       IgnoreCase="True" 
                                       UniqueNames="{StaticResource UniqueNamesList}" />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    ....
</Canvas>

and the DP itself:

public object ValidationTemplate
{
    get { return (ControlTemplate)GetValue(ValidationTemplateProperty); }
    set { SetValue(ValidationTemplateProperty, value); }
}
public static readonly DependencyProperty ValidationTemplateProperty =
    DependencyProperty.Register("ValidationTemplate"
                                , typeof(ControlTemplate)
                                , typeof(AutoCompleteComboBox)
                                , new FrameworkPropertyMetadata(new ControlTemplate()));

Thank for any help.

Ernie


Update:

Thanks Guys. I actually tried both Adi and Nit's responses. Both worked but Adi was closer to what I was looking for with not having to define a template local to the User Control. Nit's actually runs even if I do not actually create the template and just add the binding but the designer gives an error. I did have to tweak your code a bit Adi to set it on the TextBox itself:

public ControlTemplate ValidationTemplate
{
    get { return (ControlTemplate)GetValue(ValidationTemplateProperty); }
    set { SetValue(ValidationTemplateProperty, value); }
}
public static readonly DependencyProperty ValidationTemplateProperty =
    DependencyProperty.Register("ValidationTemplate"
                                , typeof(ControlTemplate)
                                , typeof(AutoCompleteComboBox)
                                , new FrameworkPropertyMetadata(new ControlTemplate(), OnValidationTemplateChanged));

private static void OnValidationTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue != null)
    {
        AutoCompleteComboBox control = (AutoCompleteComboBox)d;
        Validation.SetErrorTemplate(control.ValueTextBox, (ControlTemplate)e.NewValue);
    }
}

Thanks!

like image 266
Ernie S Avatar asked Feb 01 '26 21:02

Ernie S


2 Answers

Looking at the Validation.ErrorTemplate MSDN page, you can see that it has the IsNotDataBindable metadata property set to true, so unfortunately you can't data bind to that property.

I believe you can still handle your dependency property's OnChanged event to set that property yourself with Validation.SetErrorTemplate():

public static readonly DependencyProperty ValidationTemplateProperty =
    DependencyProperty.Register("ValidationTemplate",
                                typeof(ControlTemplate),
                                typeof(AutoCompleteComboBox),
                                new FrameworkPropertyMetadata(new ControlTemplate(), OnValidationTemplateChanged));

private static void OnValidationTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Validation.SetErrorTemplate(d, (ControlTemplate)e.NewValue);
}
like image 108
Adi Lester Avatar answered Feb 04 '26 11:02

Adi Lester


As far as I know you cannot do what you want with Binding. ErrorTemplate can be used with StaticResource.

like image 22
sexta13 Avatar answered Feb 04 '26 10:02

sexta13