在UserControl中绑定Validation.ErrorTemplate

时间:2013-10-03 15:07:24

标签: c# wpf validation xaml dependency-properties

我有一个用户控件,其文本框的text属性绑定到名为SelectedValue的依赖项属性。当用户输入文本时,该值将被另一个名为ItemsSource的DP验证,以查看它是否在那里。如果没有,我会抛出一个错误。一切正常 - 当出现错误时,UC中的TB有默认的红框。

但我希望用户能够在创建UC实例时在XAML中指定ControlTemplate。所以我想我可以创建另一个类型为ControlTemplate的DP,它们可以绑定到。这似乎有效,但我如何在XAML中实际实现呢?如果它做了类似的事情:

Validation.ErrorTemplate="{Binding ValidationTemplate}"

它抛出一个错误,说“'ErrorTemplate'属性不能被数据绑定。”以下是代码的相关部分:

<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>

和DP本身:

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()));

感谢您的帮助。

欧尼


更新

谢谢你们。我实际上尝试了Adi和Nit的回应。两者都有效,但Adi更接近我想要的,而无需定义用户控件的本地模板。即使我实际上没有创建模板并只添加绑定但设计师给出错误,Nit实际上也会运行。我确实需要调整你的代码Adi以在TextBox本身上设置它:

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);
    }
}

谢谢!

4 个答案:

答案 0 :(得分:3)

查看Validation.ErrorTemplate MSDN page,您可以看到它将IsNotDataBindable元数据属性设置为true,因此很遗憾,您无法将数据绑定到该属性。

我相信你仍然可以处理你的依赖属性的OnChanged事件,用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);
}

答案 1 :(得分:1)

据我所知,你不能用Binding做你想做的事。 ErrorTemplate可以与StaticResource一起使用。

答案 2 :(得分:1)

由于ErrorTemplate是不可绑定的,您可以做的是使用Resource设置Validation.ErrorTemplate,并在DependancyPropertyChange中用更新的值替换Resource key。

<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="{DynamicResource MyErrorTemplate}"
             >

并且依赖属性更改:

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

    private static void ValidationTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        AutoCompleteComboBox control = d as AutoCompleteComboBox;
        control.Resources["MyErrorTemplate"] = e.NewValue;
    }

答案 3 :(得分:0)

您可以定义并绑定为静态资源:

示例:

<Window.Resources>
    <ControlTemplate x:Key="errorTemplate">
        <Border BorderBrush="Red" BorderThickness="2">
            <Grid>
                <AdornedElementPlaceholder x:Name="_el" />
                <TextBlock Text="{Binding [0].ErrorContent}"
                           Foreground="Red" HorizontalAlignment="Right"
                           VerticalAlignment="Center" Margin="0,0,6,0"/>
            </Grid>
        </Border>
    </ControlTemplate>
</Window.Resources>

元素:

    <TextBox Grid.Column="1" Margin="6" Validation.ErrorTemplate="{StaticResource errorTemplate}">
        <TextBox.Text>
            <Binding Path="Name" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" >
                <Binding.ValidationRules>
                    <local:MinCharsRule MinimumChars="3" />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

注意:我从WPF Coo​​kBook 4.5中获取了这个例子,它运行良好。