WPF实现自定义样式的MessageBox

先上效果图

messagebox_error.png
messagebox_notice.png
messagebox_question.png
messagebox_warnning.png

窗体xaml代码

<local:BaseWindow x:Class="YssAMSS_YGJServo.MyUserControl.XMessageBox"
        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:YssAMSS_YGJServo"
        mc:Ignorable="d"
        Height="240" Width="400"
        MaxHeight="600" WindowStyle="None"
        MinWidth="240" 
        MinHeight="180" Style="{DynamicResource MsgWindowStyle}">
    <Window.Resources>
        <Style x:Key="MsgWindowStyle" TargetType="{x:Type local:BaseWindow}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="ResizeMode" Value="NoResize"/>
            <Setter Property="BorderBrush" Value="#ff666666"></Setter>
            <Setter Property="BorderThickness" Value="1"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:BaseWindow}">
                        <Grid Background="#fff3f7f9">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="40"></RowDefinition>
                                <RowDefinition Height="*"></RowDefinition>
                                <RowDefinition Height="40"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Grid Grid.Row="0" Background="#ffdbdbdb">
                                <Label  RenderOptions.BitmapScalingMode="Fant"  UseLayoutRounding="True"  Height="26" HorizontalAlignment="Left" Margin="14,0,0,0" Width="26" Background="{StaticResource MsgTitle_Brush}"></Label>
                                <TextBox Foreground="#ff666666" Text="{TemplateBinding Title}" BorderThickness="0" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center" Background="Transparent" VerticalContentAlignment="Center" Margin="44,0,0,0" Width="auto" Height="26" IsReadOnly="True"></TextBox>
                                <Button Margin="0,0,10,0" Background="{StaticResource CloseBrush}" HorizontalAlignment="Right" Height="26" Width="26" Command="{Binding CloseWindowCommand,RelativeSource={RelativeSource TemplatedParent}}">
                                    <Button.Style>
                                        <Style TargetType="{x:Type Button}">
                                            <Setter Property="Background" Value="{DynamicResource CloseBrush}"/>
                                            <Setter Property="Template">
                                                <Setter.Value>
                                                    <ControlTemplate TargetType="{x:Type Button}">
                                                        <Border Background="{TemplateBinding Background}">
                                                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                                        </Border>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                            <Style.Triggers>
                                                <Trigger Property="IsMouseOver" Value="True">
                                                    <Setter Property="Background" Value="{DynamicResource CloseBrush}"/>
                                                    <Setter Property="Cursor" Value="Hand"></Setter>
                                                    <Setter Property="ToolTip" Value="关闭"></Setter>
                                                </Trigger>
                                            </Style.Triggers>
                                        </Style>
                                    </Button.Style>
                                </Button>
                            </Grid>
                            <Grid Grid.Row="1">
                                <Label x:Name="MsgIcon" BorderThickness="0" Background="{Binding AIcon,RelativeSource={RelativeSource TemplatedParent}}" Height="40" Width="40" HorizontalAlignment="Left" Margin="30,0,0,0"></Label>
                                <TextBox TextWrapping="Wrap" IsReadOnly="True" Margin="80,0,30,0" BorderThickness="0" Background="Transparent" Text="{Binding AContent, RelativeSource={RelativeSource TemplatedParent}}" TextAlignment="Center" FontSize="18" Height="auto" VerticalAlignment="Center" Foreground="{StaticResource FontColor}">
                                </TextBox>
                            </Grid>
                            <Button x:Name="Confirm" FontSize="13" Foreground="White" Click="Confirm_Click" Grid.Row="2" Style="{StaticResource ButtonStyle}" HorizontalAlignment="Right" Margin="0,0,40,10"  Content="确定" Height="26" Width="54" Background="{StaticResource BlueBtnBG}"></Button>
                            <Button x:Name="Cancel" Visibility="Collapsed" FontSize="13" Click="Cancel_Click" Grid.Row="2" Style="{StaticResource ButtonStyle}" HorizontalAlignment="Right" Margin="0,0,20,10"  Content="取消" Height="26" Width="54" Foreground="#ff666666" Background="{StaticResource WhiteBG}"></Button>

                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsShowCancle" Value="true">
                                <Setter Property="Visibility" Value="Visible" TargetName="Cancel"></Setter>
                                <Setter Property="Margin" Value="0,0,110,10" TargetName="Confirm"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="ResizeMode" Value="CanResizeWithGrip">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Window}">
                                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                                    <Grid>
                                        <AdornerDecorator>
                                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
                                        </AdornerDecorator>
                                        <ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" IsTabStop="False" Visibility="Collapsed" VerticalAlignment="Bottom"/>
                                    </Grid>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <MultiTrigger>
                                        <MultiTrigger.Conditions>
                                            <Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
                                            <Condition Property="WindowState" Value="Normal"/>
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
                                    </MultiTrigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
    </Grid>
</local:BaseWindow>

窗体对应逻辑代码

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

namespace YssAMSS_YGJServo.MyUserControl
{
    /// <summary>
    /// XMessageBox.xaml 的交互逻辑
    /// </summary>
    public partial class XMessageBox : BaseWindow
    {
        private bool Result = false;
        public XMessageBox(EnumNotifyType type,string msg)
        {
            this.AContent = msg;
            switch (type)
            {
                case EnumNotifyType.Error:
                    this.Title = "错误";
                    this.AIcon = (Brush)FindResource("MsgError_Brush");
                    break;
                case EnumNotifyType.Warning:
                    this.Title = "警告";
                    this.AIcon = (Brush)FindResource("MsgWarnning_Brush");
                    break;
                case EnumNotifyType.Info:
                    this.Title = "通知";
                    this.AIcon = (Brush)FindResource("MsgInfo_Brush");
                    break;
                case EnumNotifyType.Question:
                    this.IsShowCancle = true;
                    this.Title = "询问";
                    this.AIcon = (Brush)FindResource("MsgQuestion_Brush");
                    break;
                default:
                    break;
            }
            InitializeComponent();
            this.MouseLeftButtonDown += delegate {
                DragMove();
            };
            this.KeyDown += XMessageBox_KeyDown;
        }
        /// <summary>
        /// 确定
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Confirm_Click(object sender, RoutedEventArgs e)
        {
            this.Result = true;
            this.Close();
            e.Handled = true;
        }

        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            this.Result = false;
            this.Close();
            e.Handled = true;
        }


       
        /// <summary>
        /// 显示提示消息框,
        /// owner指定所属父窗体,默认参数值为null,则指定主窗体为父窗体。
        /// </summary>
        private static bool Show(EnumNotifyType type, string mes, Window owner = null)
        {
            var res = true;
            Application.Current.Dispatcher.Invoke(new Action(() => {
                XMessageBox nb = new XMessageBox(type,mes);
                nb.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                nb.Owner = owner ?? MyFuncHelper.GetTopWindow();
                nb.ShowInTaskbar = false;
                nb.ShowDialog();
                res = nb.Result;
            }));
            return res;
        }

        public static void Info(string msg, Window owner = null)
        {
            Show(EnumNotifyType.Info, msg, owner);
        }

        public static void Warnning(string msg, Window owner = null)
        {
            Show(EnumNotifyType.Warning, msg, owner);
        }

        public static void Error(string msg, Window owner = null)
        {
            Show(EnumNotifyType.Error, msg, owner);
        }

        public static bool Question(string msg, Window owner = null)
        {
            return Show(EnumNotifyType.Question,msg,owner);
        }


        /// <summary>
        /// 弹窗的退出快捷键和Esc确认快捷键Enter
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void XMessageBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                Result = false;
                this.Close();
            }
            if (e.Key == Key.Enter)
            {
                Result = true;
                this.Close();
            }
        }

    }

    /// <summary>
    /// 通知消息类型
    /// </summary>
    public enum EnumNotifyType
    {
        [Description("错误")]
        Error,
        [Description("警告")]
        Warning,
        [Description("提示")]
        Info,
        [Description("确认")]
        Question,
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace YssAMSS_YGJServo
{
    public class BaseWindow : Window
    {
        public ICommand CloseWindowCommand { get; protected set; }
        public ICommand MaximizeWindowCommand { get; protected set; }
        public ICommand MinimizeWindowCommand { get; protected set; }
        public ICommand DoubleClickMaximizeWindowCommand { get; protected set; }

        public BaseWindow()
        {
            

            //this.Style = this.FindResource("AmssWindowStyle") as Style;
            this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            this.MaxHeight = SystemParameters.WorkArea.Height;
            this.MaxWidth = SystemParameters.WorkArea.Width;

            
            this.CloseWindowCommand = new RoutedUICommand();
            this.MaximizeWindowCommand = new RoutedUICommand();
            this.MinimizeWindowCommand = new RoutedUICommand();
            this.DoubleClickMaximizeWindowCommand = new RoutedUICommand();


            var bind = new CommandBinding(CloseWindowCommand);
            bind.Executed += new ExecutedRoutedEventHandler(CloseCommand_Execute);
            this.CommandBindings.Add(bind);

            var bind1 = new CommandBinding(MaximizeWindowCommand);
            bind1.Executed += new ExecutedRoutedEventHandler(MaxCommand_Execute);
            this.CommandBindings.Add(bind1);

            var bind3 = new CommandBinding(MinimizeWindowCommand);
            bind3.Executed += new ExecutedRoutedEventHandler(MinCommand_Execute);
            this.CommandBindings.Add(bind3);

            var bind4 = new CommandBinding(DoubleClickMaximizeWindowCommand);
            //bind4.Executed += new ExecutedRoutedEventHandler(DoubleClickMaxCommand_Execute);
        }

        

        private void CloseCommand_Execute(object sender, ExecutedRoutedEventArgs e)
        {
            this.Close();
        }
        private void MaxCommand_Execute(object sender, ExecutedRoutedEventArgs e)
        {
            this.WindowState = this.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
            e.Handled = true;
        }

        private void MinCommand_Execute(object sender, ExecutedRoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
            e.Handled = true;
        }

        private void DoubleClickMaxCommand_Execute(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                this.WindowState = this.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
                e.Handled = true;
            }
        }

        public static readonly DependencyProperty AIconProperty =
            DependencyProperty.Register("AIcon",typeof(Brush),typeof(BaseWindow),new PropertyMetadata(Brushes.DarkCyan));

        public Brush AIcon { get { return (Brush)GetValue(AIconProperty); }set { SetValue(AIconProperty,value); } }

        public static readonly DependencyProperty AContentProperty =
            DependencyProperty.Register("AContent",typeof(object),typeof(BaseWindow),new PropertyMetadata(""));

        public object AContent { get { return GetValue(AContentProperty); } set { SetValue(AContentProperty,value); } }

        public static readonly DependencyProperty IsShowCancleProperty =
            DependencyProperty.Register("IsShowCancle",typeof(bool),typeof(BaseWindow),new PropertyMetadata(false));

        public bool IsShowCancle { get { return (bool)GetValue(IsShowCancleProperty); } set { SetValue(IsShowCancleProperty,value); } }
    }
}


public static class UIHelper
    {
        //GetForegroundWindow API
        [DllImport("user32.dll")]
        static extern IntPtr GetForegroundWindow();

        /// <summary>
        /// 获取当前顶级窗体,若获取失败则返回主窗体
        /// </summary>
        public static Window GetTopWindow()
        {
            var hwnd = GetForegroundWindow();
            Window win = GetWindowFromHwnd(hwnd);
            if (hwnd == IntPtr.Zero || win == null)
            {
                return Application.Current.MainWindow;
            }
            return win;
        }

        private static Window GetWindowFromHwnd(IntPtr hwnd)
        {
            HwndSource sd = HwndSource.FromHwnd(hwnd);
            if (sd != null)
            {
                return (Window)sd.RootVisual;
            }
            return null;
        }
    }


/*禁止转载*/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352