WPF自定义控件三:消息提示框

需求:实现全局消息提示框

一:创建全局Message

public class Message
    {
        private static readonly Style infoStyle = (Style)Application.Current.Resources["InfoMessage"];
        private static readonly Style warningStyle = (Style)Application.Current.Resources["WarningMessage"];
        private static readonly Style successStyle = (Style)Application.Current.Resources["SuccessMessage"];
        private static readonly Style errorStyle = (Style)Application.Current.Resources["ErrorMessage"];

        #region 全局
        public static void Show(MessageType type, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            if (millisecondTimeOut <= 0)
            {
                isClearable = true;
            }

            MessageWindow messageWindow = MessageWindow.GetInstance();
            messageWindow.Dispatcher.VerifyAccess();

            MessageCard messageCard;
            switch (type)
            {
                default:
                case MessageType.None:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable
                    };
                    break;
                case MessageType.Info:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = infoStyle
                    };
                    break;
                case MessageType.Warning:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = warningStyle
                    };
                    break;
                case MessageType.Success:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = successStyle
                    };
                    break;
                case MessageType.Error:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = errorStyle
                    };
                    break;
            }

            messageWindow.AddMessageCard(messageCard, millisecondTimeOut);
            messageWindow.Show();
        }

        public static void Show(UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.None, element, millisecondTimeOut, isClearable);
        }

        public static void ShowInfo(UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Info, element, millisecondTimeOut, isClearable);
        }

        public static void ShowSuccess(UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Success, element, millisecondTimeOut, isClearable);
        }

        public static void ShowWarning(UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Warning, element, millisecondTimeOut, isClearable);
        }

        public static void ShowError(UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Error, element, millisecondTimeOut, isClearable);
        }

        public static void Show(MessageType type, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(type, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void Show(string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.None, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void ShowInfo(string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Info, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void ShowSuccess(string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Success, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void ShowWarning(string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Warning, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void ShowError(string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(MessageType.Error, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }
        #endregion


        #region 指定容器
        public static void Show(string containerIdentifier, MessageType type, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            if (!MessageContainer.Containers.ContainsKey(containerIdentifier))
            {
                return;
            }

            if (millisecondTimeOut <= 0)
            {
                isClearable = true;
            }

            Panel messagePanel = MessageContainer.Containers[containerIdentifier];
            messagePanel.Dispatcher.VerifyAccess();

            MessageCard messageCard;
            switch (type)
            {
                default:
                case MessageType.None:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable
                    };
                    break;
                case MessageType.Info:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = infoStyle
                    };
                    break;
                case MessageType.Warning:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = warningStyle
                    };
                    break;
                case MessageType.Success:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = successStyle
                    };
                    break;
                case MessageType.Error:
                    messageCard = new MessageCard
                    {
                        Content = element,
                        IsClearable = isClearable,
                        Style = errorStyle
                    };
                    break;
            }

            messagePanel.Children.Add(messageCard);

            // 进入动画
            Storyboard enterStoryboard = new Storyboard();

            DoubleAnimation opacityAnimation = new DoubleAnimation
            {
                From = 0,
                To = 1,
                Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            };
            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(UIElement.OpacityProperty));

            DoubleAnimation transformAnimation = new DoubleAnimation
            {
                From = -30,
                To = Application.Current.MainWindow.Height / 2-100,
                Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            };
            Storyboard.SetTargetProperty(transformAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

            enterStoryboard.Children.Add(opacityAnimation);
            enterStoryboard.Children.Add(transformAnimation);
            if (millisecondTimeOut > 0)
            {
                // 进入动画完成
                enterStoryboard.Completed += async (sender, e) =>
                {
                    await Task.Run(() =>
                    {
                        Thread.Sleep(millisecondTimeOut);
                    });

                    messagePanel.Children.Remove(messageCard);
                };

            }

            messageCard.BeginStoryboard(enterStoryboard);
            // 退出动画
            //Storyboard exitStoryboard = new Storyboard();

            //DoubleAnimation exitOpacityAnimation = new DoubleAnimation
            //{
            //    From = 1,
            //    To = Application.Current.MainWindow.Height / 2,
            //    Duration = new Duration(TimeSpan.FromMilliseconds(300)),
            //    EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            //};
            //Storyboard.SetTargetProperty(exitOpacityAnimation, new PropertyPath(UIElement.OpacityProperty));

            //DoubleAnimation exitTransformAnimation = new DoubleAnimation
            //{
            //    From = 0,
            //    To = -30,
            //    Duration = new Duration(TimeSpan.FromMilliseconds(300)),
            //    EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            //};
            //Storyboard.SetTargetProperty(exitTransformAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

            //exitStoryboard.Children.Add(exitOpacityAnimation);
            //exitStoryboard.Children.Add(exitTransformAnimation);

            //if (millisecondTimeOut > 0)
            //{
            //    // 进入动画完成
            //    enterStoryboard.Completed += async (sender, e) =>
            //    {
            //        await Task.Run(() =>
            //        {
            //            Thread.Sleep(millisecondTimeOut);
            //        });

            //        messageCard.BeginStoryboard(exitStoryboard);
            //    };

            //}

            // 退出动画完成
            //exitStoryboard.Completed += (sender, e) =>
            //{
            //    messagePanel.Children.Remove(messageCard);
            //};

            //messageCard.BeginStoryboard(enterStoryboard);
        }

        public static void Show(string containerIdentifier, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.None, element, millisecondTimeOut, isClearable);
        }

        public static void ShowInfo(string containerIdentifier, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Info, element, millisecondTimeOut, isClearable);
        }

        public static void ShowSuccess(string containerIdentifier, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Success, element, millisecondTimeOut, isClearable);
        }

        public static void ShowWarning(string containerIdentifier, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Warning, element, millisecondTimeOut, isClearable);
        }

        public static void ShowError(string containerIdentifier, UIElement element, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Error, element, millisecondTimeOut, isClearable);
        }

        public static void Show(string containerIdentifier, MessageType type, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, type, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void Show(string containerIdentifier, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.None, new TextBlock { Text = message }, millisecondTimeOut, isClearable);
        }

        public static void ShowInfo(string containerIdentifier, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Info, new TextBlock { Text = message, Foreground = new SolidColorBrush(Colors.White) }, millisecondTimeOut, isClearable);
        }

        public static void ShowSuccess(string containerIdentifier, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Success, new TextBlock { Text = message, Foreground = new SolidColorBrush(Colors.White) }, millisecondTimeOut, isClearable);
        }

        public static void ShowWarning(string containerIdentifier, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Warning, new TextBlock { Text = message, Foreground = new SolidColorBrush(Colors.White) }, millisecondTimeOut, isClearable);
        }

        public static void ShowError(string containerIdentifier, string message, int millisecondTimeOut = 3000, bool isClearable = true)
        {
            Show(containerIdentifier, MessageType.Error, new TextBlock { Text = message, Foreground = new SolidColorBrush(Colors.White) }, millisecondTimeOut, isClearable);
        }
        #endregion
    }

    public enum MessageType
    {
        None = 0,
        Info,
        Success,
        Warning,
        Error
    }

二:创建消息提示控件

1:创建名为MessageCard资源字典与MessageCard类

  <LinearGradientBrush x:Key="GridBackGrounds1" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FF061118" Offset="0.191"/>
        <GradientStop Color="#FF173A52" Offset="1"/>
    </LinearGradientBrush>

<Style x:Key="MessageCard" TargetType="{x:Type local:MessageCard}">
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="BorderBrush" Value="{StaticResource BorderGray}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="CornerRadius" Value="2.5"/>
        <Setter Property="Background" Value="{DynamicResource GridBackGrounds1}"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="ThemeColorBrush" Value="{DynamicResource DefaultForeground}"/>
        <Setter Property="Margin" Value="2.5"/>
        <Setter Property="Padding" Value="5"/>
        <Setter Property="MinHeight" Value="60"/>
        <Setter Property="MinWidth" Value="200"/>
        <Setter Property="IsShwoIcon" Value="False"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <TranslateTransform />
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MessageCard}">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding ThemeColorBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}" Margin="{TemplateBinding Margin}"
                            CornerRadius="{TemplateBinding CornerRadius}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding ThemeColorBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}" Effect="{StaticResource AllDirectionEffect}"
                                    Padding="{TemplateBinding Padding}" CornerRadius="{TemplateBinding CornerRadius}" 
                                    Grid.ColumnSpan="3"/>

                           
                            <ContentPresenter x:Name="contentPresenter" Focusable="False" Grid.Column="1"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          RecognizesAccessKey="True"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="8 0"/>
                            <Button x:Name="clearButton"  Foreground="{TemplateBinding ThemeColorBrush}"  
                                    Grid.Column="2" Style="{x:Null}" Height="20" BorderThickness="0" BorderBrush="Transparent" Background="Transparent" 
local:ButtonHelper.ButtonStyle="Link" Visibility="{TemplateBinding IsClearable,Converter={StaticResource boolToVisibility}}"
Content="X"
> </Button> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="WarningMessage" TargetType="{x:Type local:MessageCard}" BasedOn="{StaticResource MessageCard}"> <Setter Property="ThemeColorBrush" Value="{StaticResource WarningBrush}"/> <Setter Property="IconType" Value="ErrorWarningFill"/>//IOC提示类型 <Setter Property="IsShwoIcon" Value="True"/> </Style> <Style x:Key="SuccessMessage" TargetType="{x:Type local:MessageCard}" BasedOn="{StaticResource MessageCard}"> <Setter Property="ThemeColorBrush" Value="{StaticResource SuccessBrush}"/> <Setter Property="IconType" Value="CheckboxCircleFill"/> <Setter Property="IsShwoIcon" Value="True"/> </Style> <Style x:Key="ErrorMessage" TargetType="{x:Type local:MessageCard}" BasedOn="{StaticResource MessageCard}"> <Setter Property="ThemeColorBrush" Value="{StaticResource ErrorBrush}"/> <Setter Property="IconType" Value="CloseCircleFill"/> <Setter Property="IsShwoIcon" Value="True"/> </Style> <Style x:Key="InfoMessage" TargetType="{x:Type local:MessageCard}" BasedOn="{StaticResource MessageCard}"> <Setter Property="ThemeColorBrush" Value="{StaticResource InfoBrush}"/> <Setter Property="IconType" Value="InformationFill"/> <Setter Property="IsShwoIcon" Value="True"/> </Style>
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Zt.UI.Silver.Utils;

namespace Zt.UI.Silver
{
    public class MessageCard : ContentControl
    {
        public static readonly RoutedEvent CloseEvent;

        static MessageCard()
        {
            CloseEvent = EventManager.RegisterRoutedEvent("Close", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MessageCard));
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MessageCard), new FrameworkPropertyMetadata(typeof(MessageCard)));
        }

        #region 事件
        // 关闭消息事件
        public event RoutedEventHandler Close
        {
            add { base.AddHandler(MessageCard.CloseEvent, value); }
            remove { base.RemoveHandler(MessageCard.CloseEvent, value); }
        }
        #endregion

        #region 依赖属性
        public static readonly DependencyProperty CornerRadiusProperty =
          DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(MessageCard), new PropertyMetadata(default(CornerRadius)));

        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }


        public static readonly DependencyProperty ThemeColorBrushProperty =
            DependencyProperty.Register("ThemeColorBrush", typeof(SolidColorBrush), typeof(MessageCard), new PropertyMetadata(default(SolidColorBrush)));

        public SolidColorBrush ThemeColorBrush
        {
            get { return (SolidColorBrush)GetValue(ThemeColorBrushProperty); }
            set { SetValue(ThemeColorBrushProperty, value); }
        }


        public static readonly DependencyProperty IconTypeProperty =
            DependencyProperty.Register("IconType", typeof(IconType), typeof(MessageCard), new PropertyMetadata(default(IconType)));

        public IconType IconType
        {
            get { return (IconType)GetValue(IconTypeProperty); }
            set { SetValue(IconTypeProperty, value); }
        }


        public static readonly DependencyProperty IsShwoIconProperty =
            DependencyProperty.Register("IsShwoIcon", typeof(bool), typeof(MessageCard), new PropertyMetadata(default(bool)));

        public bool IsShwoIcon
        {
            get { return (bool)GetValue(IsShwoIconProperty); }
            set { SetValue(IsShwoIconProperty, value); }
        }


        public static readonly DependencyProperty IsClearableProperty =
            DependencyProperty.Register("IsClearable", typeof(bool), typeof(MessageCard), new PropertyMetadata(default(bool), OnIsClearbleChanged));

        public bool IsClearable
        {
            get { return (bool)GetValue(IsClearableProperty); }
            set { SetValue(IsClearableProperty, value); }
        }

        private static void OnIsClearbleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is MessageCard messageCard)
            {
                RoutedEventHandler handle = (sender, args) =>
                {
                    if (VisualTreeHelper.GetParent(messageCard) is Panel panel)
                    {
                        // 退出动画
                        Storyboard exitStoryboard = new Storyboard();

                        DoubleAnimation exitOpacityAnimation = new DoubleAnimation
                        {
                            From = 1,
                            To = 0,
                            Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                            EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
                        };
                        Storyboard.SetTargetProperty(exitOpacityAnimation, new PropertyPath(FrameworkElement.OpacityProperty));

                        DoubleAnimation exitTransformAnimation = new DoubleAnimation
                        {
                            From = 0,
                            To = -30,
                            Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                            EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
                        };
                        Storyboard.SetTargetProperty(exitTransformAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

                        exitStoryboard.Children.Add(exitOpacityAnimation);
                        exitStoryboard.Children.Add(exitTransformAnimation);

                        // 动画完成
                        exitStoryboard.Completed += (a, b) =>
                        {
                            panel.Children.Remove(messageCard);
                            RoutedEventArgs eventArgs = new RoutedEventArgs(MessageCard.CloseEvent, messageCard);
                            messageCard.RaiseEvent(eventArgs);
                        };

                        messageCard.BeginStoryboard(exitStoryboard);    // 执行动画
                    }
                };
                messageCard.Foreground =new SolidColorBrush( Colors.Black);
                messageCard.Loaded += (sender, arg) =>
                {
                    if (messageCard.Template.FindName("clearButton", messageCard) is Button clearButton)
                    {
                        if (messageCard.IsClearable)
                        {
                            clearButton.Click += handle;
                        }
                        else
                        {
                            clearButton.Click -= handle;
                        }
                    }
                };

                messageCard.Unloaded += (sender, arg) =>
                {
                    if (messageCard.Template.FindName("clearButton", messageCard) is Button clearButton)
                    {
                        if (messageCard.IsClearable)
                        {
                            clearButton.Click -= handle;
                        }
                    }
                };
            }
        }
        #endregion


    }
}

2:创建名为MessageWindow的窗体

<Window x:Class="Zt.UI.Silver.MessageWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Zt.UI.Silver"
        mc:Ignorable="d"
        Background="Transparent" WindowStyle="None" AllowsTransparency="True" WindowState="Maximized"
        ShowInTaskbar="False" WindowStartupLocation="CenterOwner" VerticalAlignment="Top" Topmost="True">

    <StackPanel x:Name="messageStackPanel" Margin="10">

    </StackPanel>
</Window>

后台代码:

 public partial class MessageWindow : Window
    {
        private static MessageWindow messageWindow = null;

        private MessageWindow()
        {
            InitializeComponent();
        }

        public static MessageWindow GetInstance()
        {
            if (messageWindow == null)
            {
                messageWindow = new MessageWindow();
            }
            else if (!messageWindow.IsLoaded)
            {
                messageWindow = new MessageWindow();
            }
            return messageWindow;
        }

        public void AddMessageCard(MessageCard messageCard, int millisecondTimeOut)
        {
            messageCard.Close += MessageCard_Close;

            messageStackPanel.Children.Add(messageCard);

            // 进入动画
            Storyboard enterStoryboard = new Storyboard();

            DoubleAnimation opacityAnimation = new DoubleAnimation
            {
                From = 0,
                To = 1,
                Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            };
            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(OpacityProperty));

            DoubleAnimation transformAnimation = new DoubleAnimation
            {
                From = -30,
                To = 0,
                Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            };
            Storyboard.SetTargetProperty(transformAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

            enterStoryboard.Children.Add(opacityAnimation);
            enterStoryboard.Children.Add(transformAnimation);

            // 退出动画
            Storyboard exitStoryboard = new Storyboard();

            DoubleAnimation exitOpacityAnimation = new DoubleAnimation
            {
                From = 1,
                To = 0,
                Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            };
            Storyboard.SetTargetProperty(exitOpacityAnimation, new PropertyPath(OpacityProperty));

            DoubleAnimation exitTransformAnimation = new DoubleAnimation
            {
                From = 0,
                To = -30,
                Duration = new Duration(TimeSpan.FromMilliseconds(300)),
                EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
            };
            Storyboard.SetTargetProperty(exitTransformAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

            exitStoryboard.Children.Add(exitOpacityAnimation);
            exitStoryboard.Children.Add(exitTransformAnimation);

            // 进入动画完成
            if (millisecondTimeOut > 0)
            {
                enterStoryboard.Completed += async (sender, e) =>
                {
                    await Task.Run(() =>
                    {
                        Thread.Sleep(millisecondTimeOut);
                    });

                    Dispatcher.Invoke(() =>
                    {
                        messageCard.BeginStoryboard(exitStoryboard);
                    });
                };
            }

            // 退出动画完成
            exitStoryboard.Completed += (sender, e) =>
            {
                Dispatcher.Invoke(() =>
                {
                    messageStackPanel.Children.Remove(messageCard);
                    if (messageStackPanel.Children.Count == 0)
                    {
                        this.Close();
                    }
                });
            };

            messageCard.BeginStoryboard(enterStoryboard);
        }

        /// <summary>
        /// 消息卡片关闭按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MessageCard_Close(object sender, RoutedEventArgs e)
        {
            if (messageStackPanel.Children.Count == 0)
            {
                this.Close();
            }
        }
    }

三:添加转换器BoolToVisibilityConverter

 public class BoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if ((bool)value)
            {
                return Visibility.Visible;
            }
            else
            {
                return Visibility.Collapsed;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

  

四:用法

APP引用

 <ResourceDictionary Source="pack://application:,,,/Zt.UI.Silver;component/Themes/MessageCard.xaml" />
  <Style TargetType="{x:Type local:MessageCard}" BasedOn="{StaticResource MessageCard}"/>

Main 下使用   

<zt:MessageContainer Identifier="MessageContainer" Grid.RowSpan="10"/>

CS:后台代码

局部提示 Message.ShowError("MessageContainer","123",1000);
全局提示 Message.ShowError("123",1000);

五:演示

原文地址:https://www.cnblogs.com/zt199510/p/14510575.html