Loading

WPF自定义MessageBox消息弹窗

摘要

在实际项目开发过程中,为了使其界面风格统一,恰好第三方UI库不满足又或是系统自带的又太过于简陋,那就撸起袖子肝一个自定义的出来吧!

示例代码

Tips:因都是基础代码,没什么太大难点,这里只是抛砖引玉给大家提供一个思路参考,文末有完整源代码!

1、创建一个MessageBox窗体

这里按照常规做法布局,顶部标题,内容和操作按钮

<Window
    x:Class="MessageBoxDemo.Components.MessageBoxWindow"
    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:MessageBoxDemo.Components"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MessageBoxWindow"
    Width="800"
    Height="450"
    MinWidth="360"
    MinHeight="200"
    MaxWidth="400"
    MaxHeight="300"
    BorderBrush="#37bffb"
    ResizeMode="NoResize"
    ShowInTaskbar="False"
    SizeToContent="WidthAndHeight"
    Style="{StaticResource MessageBoxWindowStyle}"
    WindowStartupLocation="CenterScreen"
    WindowStyle="None"
    mc:Ignorable="d">
    <WindowChrome.WindowChrome>
        <WindowChrome
            CaptionHeight="30"
            CornerRadius="0"
            GlassFrameThickness="0" />
    </WindowChrome.WindowChrome>
    <Window.Resources />
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid
            Margin="30"
            HorizontalAlignment="Center"
            VerticalAlignment="Center">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>

            <TextBlock
                x:Name="icon"
                Margin="10"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontFamily="/MessageBoxDemo;component/Assets/Fonts/#iconfont"
                FontSize="30"
                Foreground="White" />

            <TextBlock
                x:Name="Content"
                Grid.Column="1"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontSize="18"
                Foreground="White"
                TextWrapping="Wrap" />
        </Grid>
        <StackPanel
            Grid.Row="1"
            Margin="10"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Orientation="Horizontal">
            <Button
                x:Name="Confirm"
                Width="100"
                Height="30"
                Margin="5,0"
                Background="#285aab"
                Click="Confirm_Click"
                Content="确定"
                IsDefault="True" />
            <Button
                x:Name="Cannel"
                Width="100"
                Height="30"
                Margin="5,0"
                Background="#285aab"
                Click="Cannel_Click"
                Content="取消"
                IsCancel="True" />
        </StackPanel>
    </Grid>
</Window>

2、后台代码

看着挺多啊,其实也就多了点快捷键操作,图标根据类型显示...

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace MessageBoxDemo.Components
{
    /// <summary>
    /// MessageBoxWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MessageBoxWindow : Window
    {
        public enum MessageBoxType
        {
            Info,
            Success,
            Warning,
            Error,
            Ask
        }

        public enum ButtonType
        {
            OK = 0,
            OKCancel = 1,
            YesNoCancel = 3,
            YesNo = 4,
            None = 5,
            Custom
        }

        private ButtonType currentButtonStyle;

        private Action<MessageBoxResult> resultAction;

        public MessageBoxWindow()
        {
            InitializeComponent();
            foreach (Window item in Application.Current.Windows)
            {
                if (item.IsActive)
                {
                    Owner = item;
                    break;
                }
            }
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, CloseEvent));
        }

        private void CloseEvent(object sender, ExecutedRoutedEventArgs e)
        {
            this.Close();
            resultAction?.Invoke(MessageBoxResult.None);
        }

        private void Confirm_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
            if (currentButtonStyle == ButtonType.OKCancel || currentButtonStyle == ButtonType.Custom)
            {
                resultAction?.Invoke(MessageBoxResult.OK);
            }
            else if (currentButtonStyle == ButtonType.YesNoCancel || currentButtonStyle == ButtonType.YesNo)
            {
                resultAction?.Invoke(MessageBoxResult.Yes);
            };
        }

        private void Cannel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
            if (currentButtonStyle == ButtonType.OKCancel || currentButtonStyle == ButtonType.Custom)
            {
                resultAction?.Invoke(MessageBoxResult.Cancel);
            }
            else if (currentButtonStyle == ButtonType.YesNoCancel || currentButtonStyle == ButtonType.YesNo)
            {
                resultAction?.Invoke(MessageBoxResult.No);
            };
        }

        public void Show(string messageBoxText, string caption, MessageBoxType type = MessageBoxType.Info, ButtonType buttonType = ButtonType.OKCancel, Action<MessageBoxResult> callback = null, string confirmName = "", string cannelName = "")
        {
            this.Content.Text = messageBoxText;
            this.Title = caption;
            this.currentButtonStyle = buttonType;
            switch (buttonType)
            {
                case ButtonType.OK:
                    Cannel.Visibility = Visibility.Collapsed;
                    break;
                case ButtonType.OKCancel:
                    Cannel.Visibility = Visibility.Visible;
                    Confirm.Visibility = Visibility.Visible;
                    Confirm.Content = "确定(Enter)";
                    Cannel.Content = "取消(ESC)";
                    break;
                case ButtonType.YesNoCancel:
                case ButtonType.YesNo:
                    Cannel.Visibility = Visibility.Visible;
                    Confirm.Visibility = Visibility.Visible;
                    Confirm.Content = "是(Enter)";
                    Cannel.Content = "否(ESC)";
                    break;
                case ButtonType.None:
                    Cannel.Visibility = Visibility.Collapsed;
                    Confirm.Visibility = Visibility.Collapsed;
                    break;
                case ButtonType.Custom:
                    Cannel.Visibility = Visibility.Visible;
                    Confirm.Visibility = Visibility.Visible;
                    Cannel.Content = cannelName;
                    Confirm.Content = confirmName;
                    break;
                default:
                    break;
            }
            SetIcon(type);
            this.resultAction = callback;
            this.ShowDialog();
        }

        private void SetIcon(MessageBoxType type)
        {
            string iconText = "";
            switch (type)
            {
                case MessageBoxType.Info:
                    icon.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#00bcd4"));
                    iconText = "\xe844";
                    break;
                case MessageBoxType.Success:
                    icon.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#2db84d"));
                    iconText = "\xe68b";
                    break;
                case MessageBoxType.Warning:
                    icon.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#e9af20"));
                    iconText = "\xe61c";
                    break;
                case MessageBoxType.Error:
                    icon.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#db3340"));
                    iconText = "\xe62b";
                    break;
                case MessageBoxType.Ask:
                    icon.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#8a2be2"));
                    iconText = "\xe60c";
                    break;
                default:
                    break;
            }
            icon.Text = iconText;
        }
    }
}

Tips:这里使用到了CommandBindings,简单来说就是给元素绑定一个快捷键操作,是System.Windows为我们封装提供了一些常用快捷键操作,可以前往UIElement.CommandBindings 属性 了解详情

3、简单写点样式

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="MessageBoxWindowStyle" TargetType="Window">
        <Setter Property="Background" Value="#0a1a3a" />
        <Setter Property="BorderBrush" Value="#3f5b82" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="ShowInTaskbar" Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Window">
                    <Border
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <Border.Effect>
                            <DropShadowEffect BlurRadius="10" ShadowDepth="0" />
                        </Border.Effect>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="30" />
                                <RowDefinition />
                            </Grid.RowDefinitions>

                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0,0,1">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition />
                                        <ColumnDefinition />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock
                                        Margin="10,0,0,0"
                                        HorizontalAlignment="Left"
                                        VerticalAlignment="Center"
                                        FontSize="20"
                                        Foreground="White"
                                        Text="{TemplateBinding Title}" />
                                    <StackPanel
                                        Grid.Column="2"
                                        HorizontalAlignment="Right"
                                        VerticalAlignment="Center"
                                        Orientation="Horizontal"
                                        WindowChrome.IsHitTestVisibleInChrome="True">
                                        <!--  TODO:为了演示这里直接使用X代替关闭图标,实际使用最好使用字体图标  -->
                                        <Button
                                            Margin="0,0,10,0"
                                            Background="Transparent"
                                            BorderThickness="0"
                                            Command="ApplicationCommands.Close"
                                            Content="x"
                                            FontSize="25"
                                            Foreground="White" />
                                    </StackPanel>
                                </Grid>
                            </Border>
                            <ContentPresenter Grid.Row="1" Content="{TemplateBinding Content}" />
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

4、自定义一个静态帮助类

using System;
using System.Windows;

using static MessageBoxDemo.Components.MessageBoxWindow;

namespace MessageBoxDemo.Components
{
    /// <summary>
    /// ClassName:  MessageBoxHelper
    /// Description:自定义消息弹窗
    /// Author:     luc
    /// CreatTime:  2022-12-26 21:43:23  
    /// </summary>
    public class MessageBoxHelper
    {
        /// <summary>
        /// 信息提示
        /// </summary>
        /// <param name="content">提示信息</param>
        /// <param name="caption">标题</param>
        /// <param name="callback">返回结果</param>
        public static void Info(string content, string caption, Action<MessageBoxResult> callback = null, ButtonType button = ButtonType.OKCancel) => Show(content, caption, MessageBoxType.Info, button, callback);

        /// <summary>
        /// 成功信息提示
        /// </summary>
        /// <param name="content">提示信息</param>
        /// <param name="caption">标题</param>
        /// <param name="callback">返回结果</param>
        public static void Success(string content, string caption, Action<MessageBoxResult> callback = null, ButtonType button = ButtonType.OKCancel) => Show(content, caption, MessageBoxType.Success, button, callback);

        /// <summary>
        /// 警告信息提示
        /// </summary>
        /// <param name="content">提示信息</param>
        /// <param name="caption">标题</param>
        /// <param name="callback">返回结果</param>
        public static void Warning(string content, string caption, Action<MessageBoxResult> callback = null, ButtonType button = ButtonType.OKCancel) => Show(content, caption, MessageBoxType.Warning, button, callback);

        /// <summary>
        /// 错误信息提示
        /// </summary>
        /// <param name="content">提示信息</param>
        /// <param name="caption">标题</param>
        /// <param name="callback">返回结果</param>
        public static void Error(string content, string caption, Action<MessageBoxResult> callback = null, ButtonType button = ButtonType.OKCancel) => Show(content, caption, MessageBoxType.Error, button, callback);

        /// <summary>
        /// 询问信息提示
        /// </summary>
        /// <param name="content">提示信息</param>
        /// <param name="caption">标题</param>
        /// <param name="callback">返回结果</param>
        public static void Ask(string content, string caption, Action<MessageBoxResult> callback = null, ButtonType button = ButtonType.OKCancel) => Show(content, caption, MessageBoxType.Ask, button, callback);


        public static void Show(string messageBoxText, string caption, MessageBoxType type, ButtonType button = ButtonType.OKCancel, Action<MessageBoxResult> callback = null, string confirmName = "", string cannelName = "")
        {
            MessageBoxWindow window = new MessageBoxWindow();
            window.Show(messageBoxText, caption, type, button, callback, confirmName, cannelName);
        }
    }
}

5、使用

MessageBoxHelper.Ask("叼毛开发者抛出了一个异常,请问您要跳转百度帮开发者解决一下这个问题吗?", "系统提示", callback =>
            {
                if (callback == MessageBoxResult.OK)
                {
                    Process.Start("https://www.cnblogs.com/chonglu/");
                }
            });

效果

image-20221226220457055

image-20221226220038840

源代码

https://github.com/luchong0813/MessageBoxDemo

posted @ 2022-12-26 22:15  傲慢与偏见luc  阅读(2487)  评论(1编辑  收藏  举报