【问题标题】:Binding Validation.ErrorTemplate in UserControl在 UserControl 中绑定 Validation.ErrorTemplate
【发布时间】:2013-10-03 15:07:24
【问题描述】:

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

谢谢!

【问题讨论】:

    标签: c# wpf validation xaml dependency-properties


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      据我所知,您无法使用 Binding 做您想做的事。 ErrorTemplate 可以与 StaticResource 一起使用。

      【讨论】:

        【解决方案3】:

        由于 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;
            }
        

        【讨论】:

          【解决方案4】:

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

          例子:

          <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 第 232 页中获取了这个示例,效果很好。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-09-14
            • 2017-02-18
            • 1970-01-01
            • 2011-06-05
            • 1970-01-01
            • 2021-12-17
            • 2018-10-15
            • 1970-01-01
            相关资源
            最近更新 更多