【问题标题】:How to pass validation to a child control of a User Control如何将验证传递给用户控件的子控件
【发布时间】:2015-02-02 15:59:33
【问题描述】:

我创建了一个包含 Telerik RadMaskedInput 和标签的用户控件。用户控件是一个浮动标签输入,如下所示: http://css-tricks.com/float-labels-css/ 我遇到的问题是,当控件验证时,整个控件正在获得红色验证边框。我只需要 RadMaskedInput 框边框为红色。我已经看过其他几篇关于同一问题的帖子和帮助请求,但我似乎无法为我工作。我的控件的 XAML 如下所示:

<Grid>
        <Label x:Name="controlLabel" 
               VerticalAlignment="Bottom" 
               Padding="5,0,5,0" 
               HorizontalAlignment="Left" 
               Background="White" 
               Grid.Row="0" 
               Margin="10,0,0,0" 
               Panel.ZIndex="1" 
               IsHitTestVisible="False" 
               Template="{DynamicResource LabelControlTemplate1}"
               Content="{Binding ElementName=floatingLabelTextBox, Path=LabelContent}"
               FontFamily="{Binding ElementName=floatingLabelTextBox, Path=LabelFontFamily}"
               FontSize="{Binding ElementName=floatingLabelTextBox, Path=LabelFontSize}"
               Foreground="{DynamicResource FloatingLabelTextBox.Label.Foreground}"/>

        <telerik:RadMaskedTextInput x:Name="controlMaskedTextBox" 
                                    Mask="" 
                                    TextMode="PlainText" 
                                    FontWeight="Normal" 
                                    BorderBrush="{DynamicResource FloatingLabelTextBox.BorderBrush}" 
                                    BorderThickness="1" 
                                    SelectionOnFocus="SelectAll" 
                                    IsClearButtonVisible="False"
                                    VerticalAlignment="Bottom" 
                                    HorizontalAlignment="Left" 
                                    HorizontalContentAlignment="Right" 
                                    VerticalContentAlignment="Center" 
                                    Value="{Binding TextBoxText,
                                                   Mode=TwoWay,
                                                   UpdateSourceTrigger=LostFocus,
                                                   ValidatesOnDataErrors=True,
                                                   ValidatesOnExceptions=True,
                                                   NotifyOnValidationError=True}"
                                    GotFocus="TextBox_GotFocus" 
                                    LostFocus="TextBox_LostFocus" 
                                    Template="{DynamicResource RadMaskedTextInputControlTemplate1}"/>
</Grid>

RadMaskedTextInput 的控件模板如下所示:

<ControlTemplate x:Key="RadMaskedTextInputControlTemplate1" TargetType="{x:Type telerik:RadMaskedTextInput}">
                <Grid SnapsToDevicePixels="True" UseLayoutRounding="True">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ClearButton"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="ReadOnly">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="GridContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <SolidColorBrush Color="#5EC9C9C9"/>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledVisual">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Visible</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>-->
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DisplayText">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <SolidColorBrush Color="#FF8D8D8D"/>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Content">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <SolidColorBrush Color="#FF8D8D8D"/>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="FocusStates">
                            <VisualState x:Name="Focused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisplayTextContent">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Collapsed</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusedVisual">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Visible</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>-->
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="NotFocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisplayTextContent">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="EditorSite">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <SolidColorBrush Color="Transparent"/>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="ContentStates">
                            <VisualState x:Name="NotEmpty"/>
                            <VisualState x:Name="Empty">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisplayTextContent"/>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EmptyContent">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True">
                        <Grid x:Name="GridContainer">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <MaskedInput:PreviewInputTextBox x:Name="EditorSite" AcceptsReturn="{TemplateBinding AcceptsReturn}" Cursor="{TemplateBinding Cursor}" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" Height="{TemplateBinding Height}" IsReadOnly="{TemplateBinding IsReadOnly}" IsEnabled="{TemplateBinding IsEnabled}" MaskedInputControl="{x:Null}" Padding="{TemplateBinding Padding}" Style="{TemplateBinding TextBoxStyle}" TabIndex="{TemplateBinding TabIndex}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                                <MaskedInput:PreviewInputTextBox.TextAlignment>
                                    <Binding Path="HorizontalContentAlignment" RelativeSource="{RelativeSource TemplatedParent}">
                                        <Binding.Converter>
                                            <MaskedInput:HorizontalContentAlignmentToTextAlignmentConverter/>
                                        </Binding.Converter>
                                    </Binding>
                                </MaskedInput:PreviewInputTextBox.TextAlignment>
                            </MaskedInput:PreviewInputTextBox>
                            <Border x:Name="DisplayTextContent" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" IsHitTestVisible="False" Visibility="Collapsed">
                                <MaskedInput:PreviewInputTextBox x:Name="DisplayText" Cursor="{TemplateBinding Cursor}" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Height="{TemplateBinding Height}" IsTabStop="False" IsReadOnly="{TemplateBinding IsReadOnly}" IsEnabled="{TemplateBinding IsEnabled}" MaskedInputControl="{x:Null}" Padding="{TemplateBinding Padding}" Style="{TemplateBinding TextBoxStyle}" Text="{Binding Text, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                                    <MaskedInput:PreviewInputTextBox.TextAlignment>
                                        <Binding Path="HorizontalContentAlignment" RelativeSource="{RelativeSource TemplatedParent}">
                                            <Binding.Converter>
                                                <MaskedInput:HorizontalContentAlignmentToTextAlignmentConverter/>
                                            </Binding.Converter>
                                        </Binding>
                                    </MaskedInput:PreviewInputTextBox.TextAlignment>
                                </MaskedInput:PreviewInputTextBox>
                            </Border>
                            <Border x:Name="EmptyContent" IsHitTestVisible="False" Padding="5,0,0,0" Visibility="Collapsed">
                                <ContentControl x:Name="Content" ContentTemplate="{TemplateBinding EmptyContentTemplate}" Content="{TemplateBinding EmptyContent}" Foreground="{TemplateBinding Foreground}" FontStyle="Italic" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="False" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Border>
                            <telerik:RadButton x:Name="ClearButton" Grid.Column="1" Command="{TemplateBinding ClearCommand}" IsTabStop="False" InnerCornerRadius="3" Opacity="0" Style="{TemplateBinding ClearButtonStyle}">
                                <telerik:RadButton.Visibility>
                                    <Binding Path="IsClearButtonVisible" RelativeSource="{RelativeSource TemplatedParent}">
                                        <Binding.Converter>
                                            <telerik:BooleanToVisibilityConverter/>
                                        </Binding.Converter>
                                    </Binding>
                                </telerik:RadButton.Visibility>
                            </telerik:RadButton>
                        </Grid>
                    </Border>
                    <!--<Border x:Name="FocusedVisual" BorderBrush="#FFFFC92B" BorderThickness="1" Background="{x:Null}" CornerRadius="5" Visibility="Collapsed"/>
                <Border x:Name="DisabledVisual" BorderBrush="#FFD9D9D9" BorderThickness="1" CornerRadius="3" Visibility="Collapsed"/>-->
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        <Setter TargetName="Border" Property="BorderBrush" Value="#FFD9D9D9"/>
                    </Trigger>
                    <Trigger Property="Validation.HasError" Value="true">
                        <Setter TargetName="Border" Property="BorderBrush" Value="Red"/>
                    </Trigger>
                </ControlTemplate.Triggers>
</ControlTemplate>

后面代码中的依赖属性和dp回调:

public String TextBoxText
        {
            get
            {
                return (String)GetValue(TextBoxTextProperty);
            }
            set
            {
                SetValue(TextBoxTextProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for TextBoxText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextBoxTextProperty =
            DependencyProperty.Register("TextBoxText", typeof(String), typeof(FloatingLabelTextBox), new PropertyMetadata() { PropertyChangedCallback = UpdateTextBoxText });

        private static void UpdateTextBoxText(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FloatingLabelTextBox control = d as FloatingLabelTextBox;

            if (control != null && e.NewValue != null)
            {
                if (!string.IsNullOrWhiteSpace(e.NewValue as string))
                {
                    control.FloatLabel();
                }
                else
                {
                    control.DockLabel();
                }
            }
        }

最后,我调用/使用控件的代码:

<controls:FloatingLabelTextBox LabelContent="Batch #"
                                       TextBoxText="{Binding BatchNumber.StringValue,
                                       Mode=TwoWay,
                                       UpdateSourceTrigger=LostFocus,
                                       ValidatesOnDataErrors=True,
                                       ValidatesOnExceptions=True,
                                       NotifyOnValidationError=True,
                                       Converter={StaticResource stringToInt}}"
                                       Validation.ErrorTemplate="{x:Null}"
                                       LabelForeground="{DynamicResource FloatingLabelTextBox.Label.Foreground}"
                                       LabelFontSize="12"
                                       TextBoxWidth="150"
                                       TextBoxHeight="30"
                                       HorizontalAlignment="Left"
                                       VerticalAlignment="Bottom"
                                       Grid.Row="1"
                                       IsEnabled="{Binding BatchNumber.IsReadOnly, Mode=OneWay, Converter={StaticResource inverseBool}}" />

请注意,我使用的是 MVVM 模式。我已经从这里建模了我的代码:Validation Error Templates For UserControl,但我没有看到预期的结果。我根本没有看到任何验证边界。

我在这个问题上已经太久了。任何帮助/建议将不胜感激。

【问题讨论】:

  • 你看过Telerik 网站吗,他们有很好的文档示例
  • 是的,我有 MethodMan。我认为这超出了 Telerik 的范围。我的意思是我已经用一个简单的文本框替换了 Telerik 控件并且遇到了同样的问题。换句话说,我想要验证的作为 Telerik 控件的子项有点争议。不过谢谢你的建议。
  • 为了确保 Telerik 控件模板中没有任何东西干扰边框颜色的变化,我在另一个 (IsEnabled = false) 触发器中将边框颜色更改为红色,它完全改变了。只是不会因验证错误而改变。

标签: c# wpf validation xaml mvvm


【解决方案1】:

我没有得到任何好的答案来解决这个问题。我尝试了我能想到的一切。我有信心这是可能的,但有最后期限,我需要做点什么。我的解决方案是重新设计控件,以便扩展基本控件。在这种情况下,我扩展了 Telerik RadMaskedTextInput 控件并覆盖了控件模板,将浮动标签添加到模板中,并使用了一系列触发器来实现我所需要的。这使我可以对 Telerik 控件使用本机验证,因此无需传递任何内容。就我而言,这可能是比创建用户控件更好的解决方案。如果需要更复杂的控制,我对如何进行这项工作没有好的建议,并且希望看到评论或建议来满足我的好奇心。感谢 MethodMan 抽出时间回复。

【讨论】:

    猜你喜欢
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2012-01-22
    • 1970-01-01
    相关资源
    最近更新 更多