在UserControl中绑定Validation.ErrorTemplate

3
我有一个用户控件,其中的文本框的文本属性绑定到名为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()));

感谢任何帮助。

Ernie


更新:

谢谢大家。我实际上尝试了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个回答

3
看一下Validation.ErrorTemplate MSDN页面,你会发现它的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
据我所知,使用Binding无法实现您想要的功能。可以使用StaticResource与ErrorTemplate一起使用。

1
由于ErrorTemplate是不可绑定的,您可以将Validation.ErrorTemplate设置为资源,在DependancyPropertyChange中使用该资源,并用更新后的值替换资源键。
<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;
    }

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 CookBook 4.5页面232中获取了此示例,它非常好用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接