WPF全局窗口错误提示框

不管是CS还是BS,在需要用户提交数据的页面上,总是要做一些校验,如果校验有错就要给用户提示,WPF里自然也避免不了这个问题。一开始,我是在窗口上预留了一个TextBlock,并且设置其Visibility=Collapsed,当校验有错的时候,再把这个TextBlock显示出来,这样做是可以实现既定需求,但是这样却会影响整个窗口的布局,以下图举个例子:
这里写图片描述
现在这个TextBlock隐藏在输入框和搜索按钮之间,大家知道Visibility=Collapsed是不占布局的,一旦我将Visibility设成了Visible,搜索按钮将会往下移动,这样的体验显然不好;有的同学要说了,那初始时设置Visibility=Hidden好了,这个是占布局的,这样按钮不会下移,的确,按钮是不会下移了,但是这里莫名其妙空白一块也是影响美观的吧。

我们平时见多了APP中或者H5中的页面中央一块黑色背景的提示,这种体验还是比较好的,那在WPF里也实现一个吧~
思路很简单,在每个窗口布局里最外层Grid里与内容快平级放置一个上下左右都居中的框就可以了,然后依照实际情况控制这个框的Visibility属性。显然,这样会有不少的工作量,尤其是项目里窗口比较多的时候。再想想,对,我们要搞一个窗口模板,让有需要的窗口使用这个模板就行了。
新建一个资源字典VcreditWindowWithAlert.xaml,代码如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ControlTemplate x:Key="CustomAlertWindowTemplete" TargetType="Window">      
        <Border BorderBrush="Transparent" BorderThickness="12" x:Name="outBorder">
            <Border.Effect>
                <DropShadowEffect BlurRadius="15" Color="#000000" Opacity=".25" Direction="90" ShadowDepth="1"/>
            </Border.Effect>
            <Grid Background="White">
                <AdornerDecorator>
                    <ContentPresenter></ContentPresenter>
                </AdornerDecorator>
                <Border x:Name="alertBorder" Visibility="Collapsed" Background="#82000000" CornerRadius="8" Padding="6" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="24" MaxWidth="300">
                    <TextBlock x:Name="alertText"  TextWrapping="Wrap" Foreground="White" VerticalAlignment="Center"></TextBlock>
                    <Border.Resources>
                        <Storyboard x:Key="alertStoryboard">
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="alertBorder" Storyboard.TargetProperty="Visibility" Duration="0:0:4">
                                <ObjectAnimationUsingKeyFrames.KeyFrames>
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" >
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Visible</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                    <DiscreteObjectKeyFrame KeyTime="0:0:4" >
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Collapsed</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames.KeyFrames>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </Border.Resources>
                </Border>
            </Grid>
        </Border>
    </ControlTemplate>

    <Style x:Key="CustomAlertWindow" TargetType="Window">
        <Setter Property="AllowsTransparency" Value="True"/>
        <Setter Property="WindowStyle" Value="None"/>
        <Setter Property="Template" Value="{StaticResource CustomAlertWindowTemplete}">     </Setter>
    </Style>
</ResourceDictionary>

稍微解释一下上面代码,可以看到,还是在Grid里与ContentPresenter内容块平级放置了一个Border,这个Border里放置我们要显示的错误信息,并且我们通过一个动画5秒后自动关闭这个错误提示,另外还设置了Border的MaxWidth=”300”,是为了防止窗口较长时,这个Border会过分长。

那么,我们怎么使用上面这个模板呢,首先在App.xaml里要引入一下:

<ResourceDictionary Source="Resources/VcreditWindowWithAlert.xaml"/>

然后在需要使用的窗口里,通过Style属性引用模板:

Style="{StaticResource CustomAlertWindow}"

当需要提示错误的时候,我们通过代码找到那个动画,并且Begin它。以下是我写的一个通用方法,你可以在各个已经引入模板的窗口里调用它:

public static void ShowAlert(Window win, string msg)
{
            ControlTemplate customWindowTemplate = App.Current.Resources["CustomAlertWindowTemplete"] as ControlTemplate;
            if (customWindowTemplate!=null)
            {
                var border = customWindowTemplate.FindName("alertBorder",win) as Border;
                if (border != null)
                {
                    var textblock = border.FindChild<TextBlock>("alertText");
                    textblock.Text = msg;
                    Storyboard sb = border.Resources["alertStoryboard"] as Storyboard;
                    sb.Begin();
                }
            }
}

这里有同学可能没有FindChild方法,这个方法是MahApps.Metro.dll里的,你当然没有必要为了这一个方法去引用这个dll,VisualTreeHelper什么的也是可以实现查找子元素父元素的。

上一下效果图:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/leebin_20/article/details/78844568