显示错误,在向下移动后进行控制

发布于 2024-10-02 14:10:48 字数 3016 浏览 1 评论 0原文

因此,我尝试在输入无效时显示一条消息,假设我想要 ToolTip 之外的其他内容,该内容会一直保留到错误得到纠正。我尝试使用 ErrorTemplate

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel>
                    <Border BorderBrush="Red" BorderThickness="1">
                        <AdornedElementPlaceholder x:Name="adornedErrorElement" />
                    </Border>
                    <Label Background="Red" Foreground="White" FontSize="9" Content="{Binding ElementName=adornedErrorElement, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<StackPanel Margin="20">
    <TextBlock Text="Name" />
    <TextBox Text="{Binding Name}" />

    <TextBlock Text="Email" />
    <TextBox Text="{Binding Path=Email, ValidatesOnDataErrors=True}" />

    <Button Content="Submit" />
</StackPanel>

我得到

alt text

标签覆盖其后元素的位置。我怎样才能让它像堆栈面板中的另一个元素一样工作?

更新:使用 VSM

现在,我想更进一步,将错误标签向上和向下设置动画。我正在考虑遵循 @robertos 答案的 VSM。我尝试在 Blend 中实现。我遇到的一些问题。我尝试

<ControlTemplate TargetType="{x:Type TextBox}">
    <StackPanel Orientation="Vertical">
        <Microsoft_Windows_Themes:ListBoxChrome ...>
        <VisualStateManager.VisualStateGroups>
                ...
        </VisualStateManager.VisualStateGroups>
        <ScrollViewer ... />
        </Microsoft_Windows_Themes:ListBoxChrome>
        <Label Content="Error Here" />
    </StackPanel>
</ControlTemplate>

过然后我失去了对 Blend 中 VisualStates 的访问。然后我尝试了

<Microsoft_Windows_Themes:ListBoxChrome>
    <StackPanel>
        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="2,0,-2,0"/>
    <TextBlock x:Name="textBlock" Background="Red" Foreground="White" FontWeight="Bold" Text="Hello" Visibility="Collapsed" />
    </StackPanel>
</Microsoft_Windows_Themes:ListBoxChrome>

不理想,因为 StackPanel 在边界内。另外,我对动画的尝试看起来很奇怪

http://screenr.com/byk

http://download.macromedia .com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345'>http://screenr.com/Content/assets/screenr_1116090935.swf '>http://screenr.com/Content/assets/screenr_1116090935.swf' flashvars='i=130553'allowFullScreen='true'width='560'height='345'pluginspage='http://www.macromedia.com/go/getflashplayer' >

第一,我必须隐藏标签,而不是仅仅折叠动画的不透明度。我希望标签看起来像是从文本框中出来的

So I am trying to have a message displayed when the input is invalid, suppose I want something other than a ToolTip, something that stays until the error is corrected. I tried having an ErrorTemplate

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel>
                    <Border BorderBrush="Red" BorderThickness="1">
                        <AdornedElementPlaceholder x:Name="adornedErrorElement" />
                    </Border>
                    <Label Background="Red" Foreground="White" FontSize="9" Content="{Binding ElementName=adornedErrorElement, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<StackPanel Margin="20">
    <TextBlock Text="Name" />
    <TextBox Text="{Binding Name}" />

    <TextBlock Text="Email" />
    <TextBox Text="{Binding Path=Email, ValidatesOnDataErrors=True}" />

    <Button Content="Submit" />
</StackPanel>

I get

alt text

Where the label overlays elements after it. How can I have it such that it works just like another element in the stackpanel?

UPDATE: Using The VSM

Now, I want to go 1 step further and animate the error label up and down. I am considering VSM following @robertos answer. I tried implementing in in Blend. A few problems I faced. I tried

<ControlTemplate TargetType="{x:Type TextBox}">
    <StackPanel Orientation="Vertical">
        <Microsoft_Windows_Themes:ListBoxChrome ...>
        <VisualStateManager.VisualStateGroups>
                ...
        </VisualStateManager.VisualStateGroups>
        <ScrollViewer ... />
        </Microsoft_Windows_Themes:ListBoxChrome>
        <Label Content="Error Here" />
    </StackPanel>
</ControlTemplate>

Then I lost access to VisualStates in Blend. Then I tried

<Microsoft_Windows_Themes:ListBoxChrome>
    <StackPanel>
        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="2,0,-2,0"/>
    <TextBlock x:Name="textBlock" Background="Red" Foreground="White" FontWeight="Bold" Text="Hello" Visibility="Collapsed" />
    </StackPanel>
</Microsoft_Windows_Themes:ListBoxChrome>

Not ideal as the StackPanel is within the border. Also my attempts at animation looks just weird

http://screenr.com/byk

http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345'>http://screenr.com/Content/assets/screenr_1116090935.swf' >http://screenr.com/Content/assets/screenr_1116090935.swf' flashvars='i=130553' allowFullScreen='true' width='560' height='345' pluginspage='http://www.macromedia.com/go/getflashplayer' >

1st I must make the label hidden instead of collapsed the animate just the opacity. I want the label to appear like its coming out from the textbox

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

[旋木] 2024-10-09 14:10:48

该元素必须是 VisualTree 中同一个 StackPanel 的一部分,正如您所注意到的, Validation.ErrorTemplate 的情况并非如此。实现此目的的一种方法是重新模板化 TextBox 并为折叠错误标签腾出位置,该标签将在 Validation.HasError 上变得可见。您需要添加对PresentationFramework.Aero 的引用。

xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"

Xaml

<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
    <GradientStop Color="#ABADB3" Offset="0.05"/>
    <GradientStop Color="#E2E3EA" Offset="0.07"/>
    <GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="LabelValidationTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <StackPanel Orientation="Vertical">
                    <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
                        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Microsoft_Windows_Themes:ListBoxChrome>
                    <Label StackPanel.ZIndex="-1" Name="errorLabel" Height="22" Margin="0,-22,0,0" Background="Red" Foreground="White" FontSize="9" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Validation.Errors)[0].ErrorContent}" />
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard TargetName="errorLabel" TargetProperty="Margin">
                                    <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,-22,0,0"/>
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,0,0,0"/>
                                    </ThicknessAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard TargetName="errorLabel" TargetProperty="Margin">
                                    <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,0,0,0"/>
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,-22,0,0"/>
                                    </ThicknessAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

更新

添加了标签的边距动画。当 Validation.HasError 为 True 时,它​​将“滑出”TextBox;当 Validation.HasError 为 False 时,它​​将“滑回”TextBox。

The element would have to be a part of the same StackPanel in the VisualTree which is not the case with the Validation.ErrorTemplate as you noticed. One way to do this would be to retemplate the TextBox and make place for a Collapsed error Label which will turn visible on Validation.HasError. You'll need to add a reference to PresentationFramework.Aero.

xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"

Xaml

<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
    <GradientStop Color="#ABADB3" Offset="0.05"/>
    <GradientStop Color="#E2E3EA" Offset="0.07"/>
    <GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="LabelValidationTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <StackPanel Orientation="Vertical">
                    <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
                        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Microsoft_Windows_Themes:ListBoxChrome>
                    <Label StackPanel.ZIndex="-1" Name="errorLabel" Height="22" Margin="0,-22,0,0" Background="Red" Foreground="White" FontSize="9" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Validation.Errors)[0].ErrorContent}" />
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard TargetName="errorLabel" TargetProperty="Margin">
                                    <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,-22,0,0"/>
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,0,0,0"/>
                                    </ThicknessAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard TargetName="errorLabel" TargetProperty="Margin">
                                    <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,0,0,0"/>
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,-22,0,0"/>
                                    </ThicknessAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Update

Added Margin animation of the Label. It will "slide out" of the TextBox when Validation.HasError is True and "slide back in" to the TextBox when Validation.HasError is False.

拧巴小姐 2024-10-09 14:10:48

您可以使用可视状态管理器并自定义无效状态,而不是使用 ErrorTemplate。通过这样做,除了能够将您的更改集成到实际控件(这会影响布局)之外,您还可以非常轻松地为状态更改设置动画。

如果您需要有关视觉状态的更多指导,请随时询问。

Instead of using ErrorTemplate, you could use the Visual State Manager and customize the Invalid State. By doing that, besides being able to integrate your changes to the actual control (which affects layout), you'll also get the ability to animate state changes very easily as well.

If you need more guidance on Visual States don't hesitate to ask.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文