【问题标题】:Silverlight: How do you implement validation in custom controls?Silverlight:您如何在自定义控件中实现验证?
【发布时间】:2011-04-07 21:55:16
【问题描述】:

如何在自定义控件中实现验证?我希望复制您会看到的标准验证逻辑,其中 TextBox 数据绑定到公开 IDataErrorInfo 或 INotifyDataErrorInfo 的模型或视图模型。

【问题讨论】:

  • 您到底想改变什么?据我所知,验证是绑定的属性,当绑定失败时,会引发事件 BindingValidationError。标准控件和自定义控件没有区别。
  • BindingValidationError:控件作者通常不应在控件设计和控件类实现中引发或处理此事件。
  • 想象一下,您正在从头开始编写自己的文本框。您将如何实现验证工具提示之类的功能?

标签: silverlight


【解决方案1】:

要实现验证,您应该将“ValidationStates”组添加到控件的 VisualStateManager。

我将用TestProperty 属性说明简单的自定义控件TestControl

Generic.xaml 中的样式,根据状态显示蓝色文本或带有第一条错误消息的红色边框:

<Style TargetType="local:TestControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:TestControl">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ValidationStates">
                            <VisualState x:Name="Valid" />
                            <VisualState x:Name="InvalidFocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvalidBorder" Storyboard.TargetProperty="Visibility" Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="InvalidUnfocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvalidBorder" Storyboard.TargetProperty="Visibility" Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>    
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <TextBlock Text="{TemplateBinding TestProperty}" Foreground="Blue" />
                    <Border x:Name="InvalidBorder"  BorderBrush="Red" BorderThickness="2" Visibility="Collapsed">
                        <TextBlock Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" Foreground="Red" FontWeight="Bold" />
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

有3种状态:

  • 有效 - 没有验证错误。
  • InvalidFocused - 当您将焦点设置到处于无效状态的控件时应用。默认控件在此状态下显示红色弹出窗口和红色边框,但在我的特定示例中,为简单起见,我不显示它。用户可以通过使用 Tab 键盘按钮或单击 TextBox 等可聚焦的内部控件来调用此状态。
  • InvalidUnfocused - 当控件处于无效状态但未获得焦点时应用。

这里是控件的代码,它只包含一个属性:

public class TestControl : Control
{
    public TestControl()
    {
        this.DefaultStyleKey = typeof(TestControl);
    }

    public string TestProperty
    {
        get { return (string)GetValue(TestPropertyProperty); }
        set { SetValue(TestPropertyProperty, value); }
    }

    public static readonly DependencyProperty TestPropertyProperty =
        DependencyProperty.Register("TestProperty", typeof(string), typeof(TestControl), new PropertyMetadata(null));
}

之后如果你使用IDataErrorInfo,正确的xaml是:

<local:TestControl TestProperty="{Binding SomeModelProperty, ValidatesOnDataErrors=True}" />

对于INotifyDataErrorInfo,正确的xaml更加简单:

<local:TestControl TestProperty="{Binding SomeModelProperty}" />

【讨论】:

  • 谢谢,这很有意义。您是否有兴趣撰写一篇关于在 Silverlight 中设计自定义控件的完整文章?
  • @Jonathan Allen “设计”这个词是什么意思:从头实现还是在 Expression Blend 中进行装饰?从开发人员的角度来看,我一般可以撰写有关自定义控件的文章,但我的设计师技能还有很多不足之处。
  • 我正在寻找的是支持所有核心功能(如模板、验证和数据绑定)所需的步骤。一旦完成,已经有无数关于让它变得漂亮的文章。给我留言,我们可以谈谈细节:jonathan@infoq.com
  • @Jonathan Allen 我试图写一篇关于从头开始创建自定义控件的文章:vortexwolf.wordpress.com/2011/04/14/…
  • @imdadhusen 在您的视图模型中实现 INotifyDataErrorInfo 或 IDataErrorInfo 接口。您可以从我的博文中下载示例应用程序:vortexwolf.wordpress.com/2011/10/01/…
猜你喜欢
  • 2020-06-19
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
相关资源
最近更新 更多