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/");
}
});