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

感谢您的帮助。

厄尼


更新:

多谢你们。我实际上尝试了 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

4 回答 4

3

查看Validation.ErrorTemplateMSDN 页面,您可以看到它的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);
}
于 2013-10-03T15:18:23.283 回答
1

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

<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;
    }
于 2013-10-03T15:33:04.363 回答
1

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

于 2013-10-03T15:18:49.133 回答
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 Page 232 中获取了这个例子,它工作得很好。

于 2016-03-30T22:46:25.497 回答