基于WPF简单实现Meesage消息提醒

寻技术 C#编程 2023年12月18日 135

WPF 简单实现 Meesage 消息提醒

框架使用.NET4 至 .NET6

Visual Studio 2022;

实现方式通过获取当前焦点的 Window 然后对它添加装饰器,将 Meesage 内部添加 ListBox 用作记录显示消息。

新建装饰器 MessageAdorner.cs 提供一个公共方法 PushMessage 提供可传参数

  • message 消息文本,居中显示从 Y 轴 0 方向屏幕下添加。
  • MessageBoxImage 消息类型枚举
  • 消息添加到 ListBox 集合中后,使用 DispatcherTimer 用来记时关闭 MessageItem

新建 MessageItem.cs 基础 ListBoxItem 用来展示每条 Meesage 消息

添加一个依赖属性 MessageType 枚举,用来区分显示的 Icon 与文本字体颜色

新建 MessageItem.xaml 的模板

对 EventTrigger Loaded 添加动画 ScaleY 从 0 到 1

新建 Message.cs 帮助类实现全局方便使用

添加静态方法 PushMessage 判断装饰器是否为空,如果为空则创建装饰,如果不为空则调用装饰器内部 PushMessage 方法

下期会写一个增加关闭消息,消息谈出,文本居中等。

此项目使用了 WPFDevelopers 的引用

实现代码

1)新增 MessageItem.cs 代码如下:

using System.Windows;
using System.Windows.Controls;
namespace MessageSample
{
    public class MessageItem : ListBoxItem
    {
        public MessageBoxImage MessageType
        {
            get { return (MessageBoxImage)GetValue(MessageTypeProperty); }
            set { SetValue(MessageTypeProperty, value); }
        }
        public static readonly DependencyProperty MessageTypeProperty =
            DependencyProperty.Register("MessageType", typeof(MessageBoxImage), typeof(MessageItem), new PropertyMetadata(MessageBoxImage.Information));
    }
}

2)新增 MessageAdorner.cs 代码如下:

public class MessageAdorner : Adorner
    {
        private ListBox listBox;
        private UIElement _child;
        private FrameworkElement adornedElement;
        public MessageAdorner(UIElement adornedElement) : base(adornedElement)
        {
            this.adornedElement = adornedElement as FrameworkElement;
        }
        public void PushMessage(string message, MessageBoxImage type = MessageBoxImage.Information)
        {
            if (listBox == null)
            {
                listBox = new ListBox() { Style = null ,BorderThickness = new Thickness(0) ,Background = Brushes.Transparent};
                Child = listBox;
            }
            var item = new MessageItem{ Content = message , MessageType = type};
            var timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(10);
            timer.Tick += (sender, e) =>
            {
                listBox.Items.Remove(item);
                timer.Stop();
            };
            listBox.Items.Insert(0,item);
            timer.Start();
        }
        public UIElement Child
        {
            get => _child;
            set
            {
                if (value == null)
                {
                    RemoveVisualChild(_child);
                    _child = value;
                    return;
                }
                AddVisualChild(value);
                _child = value;
            }
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return _child != null ? 1 : 0;
            }
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            var x = (adornedElement.ActualWidth - _child.DesiredSize.Width) / 2;
            _child.Arrange(new Rect(new Point(x, 0), _child.DesiredSize));
            return finalSize;
        }
        protected override Visual GetVisualChild(int index)
        {
            if (index == 0 && _child != null) return _child;
            return base.GetVisualChild(index);
        }
    }

3)新增 Message.cs 代码如下:

public static class Message
    {
        private static MessageAdorner messageAdorner;
        public static void PushMessage( string message, MessageBoxImage type = MessageBoxImage.Information)
        {
            if (messageAdorner != null)
            {
                messageAdorner.PushMessage(message, type);
                return;
            }
            Window win = null;
            if (Application.Current.Windows.Count > 0)
            {
                win = Application.Current.Windows.OfType<Window>().FirstOrDefault(o => o.IsActive);
                if (win == null)
                    win = Application.Current.Windows.OfType<Window>().First(o => o.IsActive);
            }
            var layer = GetAdornerLayer(win);
            if (layer == null)
                throw new Exception("not AdornerLayer is null");
            messageAdorner = new MessageAdorner(layer);
            layer.Add(messageAdorner);
            messageAdorner.PushMessage(message, type);
        }
        static AdornerLayer GetAdornerLayer(Visual visual)
        {
            var decorator = visual as AdornerDecorator;
            if (decorator != null)
                return decorator.AdornerLayer;
            var presenter = visual as ScrollContentPresenter;
            if (presenter != null)
                return presenter.AdornerLayer;
            var visualContent = (visual as Window)?.Content as Visual;
            return AdornerLayer.GetAdornerLayer(visualContent ?? visual);
        }
    }

4)新增 MessageItem.xaml 代码如下:

 <Style BasedOn="{StaticResource WD.ControlBasicStyle}" TargetType="{x:Type local:MessageItem}">
                <Setter Property="Background" Value="{DynamicResource WD.BackgroundSolidColorBrush}" />
                <Setter Property="Width" Value="300" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:MessageItem}">
                            <wd:SmallPanel
                                Name="PART_SmallPanel"
                                Margin="4"
                                RenderTransformOrigin=".5,0">
                                <wd:SmallPanel.RenderTransform>
                                    <ScaleTransform />
                                </wd:SmallPanel.RenderTransform>
                                <Border
                                    Name="PART_Border"
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    CornerRadius="{Binding Path=(wd:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
                                    Effect="{StaticResource WD.NormalShadowDepth}"
                                    SnapsToDevicePixels="True"
                                    UseLayoutRounding="True" />
                                <Border Padding="10">
                                    <DockPanel>
                                        <Path
                                            x:Name="PART_Path"
                                            Width="15"
                                            Height="15"
                                            Data="{StaticResource WD.InformationGeometry}"
                                            Fill="{DynamicResource WD.PrimaryNormalSolidColorBrush}"
                                            Stretch="Fill" />
                                        <TextBlock
                                            Grid.Row="1"
                                            Grid.Column="1"
                                            Margin="5,0"
                                            VerticalAlignment="Center"
                                            FontSize="{DynamicResource WD.NormalFontSize}"
                                            Foreground="{TemplateBinding Foreground}"
                                            Text="{TemplateBinding Content}"
                                            TextWrapping="Wrap" />
                                    </DockPanel>
                                </Border>
                            </wd:SmallPanel>
                            <ControlTemplate.Triggers>
                                <Trigger Property="MessageType" Value="Warning">
                                    <Setter TargetName="PART_Path" Property="Data" Value="{StaticResource WD.WarningGeometry}" />
                                    <Setter TargetName="PART_Path" Property="Fill" Value="{StaticResource WD.WarningSolidColorBrush}" />
                                    <Setter Property="Foreground" Value="{StaticResource WD.WarningSolidColorBrush}" />
                                </Trigger>
                                <Trigger Property="MessageType" Value="Error">
                                    <Setter TargetName="PART_Path" Property="Data" Value="{StaticResource WD.ErrorGeometry}" />
                                    <Setter TargetName="PART_Path" Property="Fill" Value="{StaticResource WD.DangerSolidColorBrush}" />
                                    <Setter Property="Foreground" Value="{StaticResource WD.DangerSolidColorBrush}" />
                                </Trigger>
                                <Trigger Property="MessageType" Value="Information">
                                    <Setter TargetName="PART_Path" Property="Data" Value="{StaticResource WD.InformationGeometry}" />
                                    <Setter TargetName="PART_Path" Property="Fill" Value="{StaticResource WD.SuccessSolidColorBrush}" />
                                    <Setter Property="Foreground" Value="{StaticResource WD.SuccessSolidColorBrush}" />
                                </Trigger>
                                <Trigger Property="MessageType" Value="Question">
                                    <Setter TargetName="PART_Path" Property="Data" Value="{StaticResource WD.QuestionGeometry}" />
                                    <Setter TargetName="PART_Path" Property="Fill" Value="{StaticResource WD.NormalSolidColorBrush}" />
                                    <Setter Property="Foreground" Value="{StaticResource WD.NormalSolidColorBrush}" />
                                </Trigger>
                                <EventTrigger RoutedEvent="Loaded">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation
                                                Storyboard.TargetName="PART_SmallPanel"
                                                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                                From="0"
                                                To="1"
                                                Duration="0:0:0.2" />
                                            <DoubleAnimation
                                                Storyboard.TargetName="PART_SmallPanel"
                                                Storyboard.TargetProperty="Opacity"
                                                From="0.01"
                                                To="1"
                                                Duration="0:0:0.2" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                                <Trigger SourceName="PART_SmallPanel" Property="Opacity" Value="0">
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

5)新增 示例 代码如下:

<wd:Window
    x:Class="MessageSample.MainWindow"
    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:local="clr-namespace:MessageSample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
    Title="WPFDevelopers - Message"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <StackPanel
            Grid.Row="1"
            HorizontalAlignment="Center"
            VerticalAlignment="Bottom"
            Orientation="Horizontal">
            <Button
                Click="AddButton_Click"
                Content="Info Message"
                Style="{StaticResource WD.SuccessPrimaryButton}"
                Tag="Info" />
            <Button
                Click="AddButton_Click"
                Content="Error Message"
                Style="{StaticResource WD.DangerPrimaryButton}"
                Tag="Error" />
            <Button
                Click="AddButton_Click"
                Content="Warning Message"
                Style="{StaticResource WD.WarningPrimaryButton}"
                Tag="Warning" />
            <Button
                Click="AddButton_Click"
                Content="Question Message"
                Style="{StaticResource WD.PrimaryButton}"
                Tag="Question" />
            <Button
                Click="AddButton_Click"
                Content="Very Long Message"
                Style="{StaticResource WD.SuccessPrimaryButton}"
                Tag="Long" />
        </StackPanel>
    </Grid>
</wd:Window>

6) 示例 代码如下:

using System.Windows;
using System.Windows.Controls;
namespace MessageSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void AddButton_Click(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            switch (btn.Tag)
            {
                case "Info":
                    Message.PushMessage("这是一条成功消息", MessageBoxImage.Information);
                    break;
                case "Error":
                    Message.PushMessage("这是一条错误消息", MessageBoxImage.Error);
                    break;
                case "Warning":
                    Message.PushMessage("这是一条警告消息", MessageBoxImage.Warning);
                    break;
                case "Question":
                    Message.PushMessage("这是一条询问消息", MessageBoxImage.Question);
                    break;
                default:
                    Message.PushMessage("这是一条很长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长消息", MessageBoxImage.Information);
                    break;
            }
        }
    }
}

效果图

以上就是基于WPF简单实现Meesage消息提醒的详细内容,更多关于WPF Meesage消息提醒的资料请关注寻技术其它相关文章!

关闭

用微信“扫一扫”