C# wpf 实现自定义按钮及Toast的MessageBox

WPF 自定义MessageBox系列

第一节 简单MessageBox
第二节 倒计时MessageBox
第三节 自定义按钮的MessageBox(本节)
第四节 界面操作分离的MessageBox
第五节 替换系统的MessageBox



前言

本篇是在上一篇《C# wpf 实现自定义倒计时MessageBox》的基础上添加自定义按钮功能,可以设置按钮名称以及是否显示。这就灵活了使用场景


一、代码

1、MessageBox.xaml

<Window x:Class="WpfApp1.MessageBox"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MessageBox" 
        AllowsTransparency="True"
        Background="Transparent"
        ResizeMode="NoResize"
        ShowInTaskbar="False"
        Topmost="True"
        WindowStartupLocation="CenterScreen"
        Width="600"
        Height="260"
        WindowStyle="None"
        Closing="Window_Closing"
        Loaded="Window_Loaded"
        >
    <Viewbox>
        <Grid  Width="600" Height="260">
            <Border  Margin="10" Background="White"    >
                <Border.Effect>
                    <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.5"/>
                </Border.Effect>
                <Border.Style>
                    <Style TargetType="Border">
                        <Style.Triggers>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition  Binding="{Binding NoText}" Value="{x:Null}"/>
                                    <Condition  Binding="{Binding YesText}" Value="{x:Null}"/>
                                </MultiDataTrigger.Conditions>
                                <MultiDataTrigger.Setters>
                                    <Setter  Property="Width" Value="400"></Setter>
                                    <Setter  Property="Height" Value="120"></Setter>
                                </MultiDataTrigger.Setters>
                            </MultiDataTrigger>
                        </Style.Triggers>
                    </Style>
                </Border.Style>
                <Grid Margin="20">
                    <StackPanel VerticalAlignment="Center">
                        <TextBlock   Text="{Binding Context}" Margin="0,0,0,0"    HorizontalAlignment="Center"  VerticalAlignment="Center" FontSize="48"  Foreground="Gray"/>
                        <Control Height="40">
                            <Control.Template>
                                <ControlTemplate>
                                    <ControlTemplate.Triggers>
                                        <MultiDataTrigger>
                                            <MultiDataTrigger.Conditions>
                                                <Condition  Binding="{Binding NoText}" Value="{x:Null}"/>
                                                <Condition  Binding="{Binding YesText}" Value="{x:Null}"/>
                                            </MultiDataTrigger.Conditions>
                                            <MultiDataTrigger.Setters>
                                                <Setter  Property="Visibility" Value="Collapsed"></Setter>
                                            </MultiDataTrigger.Setters>
                                        </MultiDataTrigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Control.Template>
                        </Control>
                    </StackPanel>
   
                    <StackPanel VerticalAlignment="Bottom"  Orientation="Horizontal" HorizontalAlignment="Center" >
                        <Button      Height="64" Width="144"  Click="No_Button_Click"  Cursor="Hand"  >
                            <Button.Template>
                                <ControlTemplate  TargetType="{x:Type Button}">
                                    <Border   Background="White"  BorderBrush="#cccccc"  >
                                        <Border.Effect>
                                            <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.2"/>
                                        </Border.Effect>
                                        <TextBlock  Name="text"   FontSize="24"    Foreground="Gray"  HorizontalAlignment="Center" VerticalAlignment="Center">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="{}{0}({1})">
                                                    <Binding Path="NoText" />
                                                    <Binding Path="NoLeftTime.TotalSeconds"/>
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <DataTrigger Binding="{Binding NoLeftTime.TotalSeconds}" Value="-1">
                                            <Setter TargetName="text" Property="Text" Value="{Binding NoText}"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding NoText}" Value="{x:Null}">
                                            <Setter  Property="Visibility" Value="Collapsed"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding YesText}" Value="{x:Null}">
                                            <Setter  Property="Margin" Value="0"></Setter>
                                        </DataTrigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Button.Template>
                        </Button>
                        <Control Width="30">
                            <Control.Template>
                                <ControlTemplate>
                                    <ControlTemplate.Triggers>
                                        <DataTrigger Binding="{Binding NoText}" Value="{x:Null}">
                                            <Setter  Property="Visibility" Value="Collapsed"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding YesText}" Value="{x:Null}">
                                            <Setter  Property="Visibility" Value="Collapsed"></Setter>
                                        </DataTrigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Control.Template>
                        </Control>
                        <Button    Height="64" Width="144"  Click="Yes_Button_Click" Cursor="Hand" >
                            <Button.Template>
                                <ControlTemplate  TargetType="{x:Type Button}">
                                    <Border  Background="Gray"  >
                                        <Border.Effect>
                                            <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.2"/>
                                        </Border.Effect>
                                        <TextBlock  Name="text"  FontSize="24"   Foreground="White"  HorizontalAlignment="Center" VerticalAlignment="Center">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="{}{0}({1})">
                                                    <Binding Path="YesText" />
                                                    <Binding Path="YesLeftTime.TotalSeconds" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <DataTrigger Binding="{Binding YesLeftTime.TotalSeconds}" Value="-1">
                                            <Setter TargetName="text" Property="Text" Value="{Binding YesText}"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding YesText}" Value="{x:Null}">
                                            <Setter  Property="Visibility" Value="Collapsed"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding NoText}" Value="{x:Null}">
                                            <Setter  Property="Margin" Value="0"></Setter>
                                        </DataTrigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Button.Template>
                        </Button>
                    </StackPanel>
                </Grid>
            </Border>
        </Grid>
    </Viewbox>
</Window>

2、MessageBox.xaml.cs

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Threading;
namespace WpfApp1
{
    public class MessageResult
    {
        /// <summary>
        /// 结果,Yes为true,No为false
        /// </summary>
        public bool IsYes { get; set; }
        public TimeSpan YesLeftTime { get; set; }

        public TimeSpan NoLeftTime { get; set; }
    }
    public class MessageBoxEventArgs : EventArgs
    {
        /// <summary>
        /// 结果,Yes为true,No为false
        /// </summary>
        public MessageResult Result { get; set; }
    }
    /// <summary>
    /// MessageBox.xaml 的交互逻辑
    /// </summary>
    public partial class MessageBox : Window, INotifyPropertyChanged
    {
        public  event EventHandler<MessageBoxEventArgs> Result;
        public event PropertyChangedEventHandler PropertyChanged;
        string _context = "Ensure?";
        public string Context
        {
            get { return _context; }
            set { _context = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Context")); }
        }

        string _yesText = "Yes";
        public string YesText
        {
            get { return _yesText; }
            set { _yesText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("YesText")); }
        }
        string _noText = "No";
        public string NoText
        {
            get { return _noText; }
            set { _noText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NoText")); }
        }

        TimeSpan _yesLeftTime = TimeSpan.FromSeconds(-1);
        public TimeSpan YesLeftTime 
        {
            get { return _yesLeftTime; }
            set { _yesLeftTime = value; PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("YesLeftTime"));}
        }
        TimeSpan _noLeftTime= TimeSpan.FromSeconds(-1);
        public TimeSpan NoLeftTime
        {
            get { return _noLeftTime; }
            set { _noLeftTime = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NoLeftTime")); }
        }
        bool _isLegal = false;
        DispatcherTimer _timer;
        public MessageBox()
        {
            InitializeComponent();
            DataContext = this;
      
        }      
        public static void Show(string context, EventHandler<MessageBoxEventArgs> result)
        {
            var mb = new MessageBox();
            mb.Context = context;
            mb.Result += result;
            mb.Show();
        }

        public static MessageResult ShowDialog(string context)
        {
            return ShowDialog(context,null,null, null, null);
        }
        public static MessageResult ShowDialog(string context, string yesText, string noText)
        {
            return ShowDialog(context, yesText, noText, null, null);
        }
        public static void Toast(string context, TimeSpan stayTime)
        {
          App.Current.Dispatcher.BeginInvoke(new Action(()=> {
              ShowDialog(context, null, null, stayTime, null);
          }));     
        }

        public static MessageResult ShowDialog(string context,TimeSpan ?yestCountDown, TimeSpan? noCountDown)
        {
            return ShowDialog(context, null, null, yestCountDown, noCountDown);
        }

        public static MessageResult ShowDialog(string context,string yesText,string noText ,TimeSpan? yestCountDown, TimeSpan? noCountDown)
        {
            var mb = new MessageBox();
            mb.Context = context;
            MessageResult r = null;
            mb.YesText = yesText;
            mb.NoText = noText;
            if (yestCountDown != null)
            {
                mb.YesLeftTime = yestCountDown.Value;
            }
            if (noCountDown != null)
            {
                mb.NoLeftTime = noCountDown.Value;
            }
            mb.Result += (s, e) => {
                r = e.Result;
            };
            mb.ShowDialog();
            return r;
        }


        private void No_Button_Click(object sender, RoutedEventArgs e)
        {
            _isLegal = true;
            Close();
            Result?.Invoke(this, new MessageBoxEventArgs() { Result = new MessageResult() { IsYes=false, YesLeftTime=this.YesLeftTime, NoLeftTime= this.NoLeftTime } });
        }
        private void Yes_Button_Click(object sender, RoutedEventArgs e)
        {
            _isLegal = true;
            Close();
            Result?.Invoke(this, new MessageBoxEventArgs() { Result = new MessageResult() { IsYes = true, YesLeftTime = this.YesLeftTime, NoLeftTime = this.NoLeftTime } });
        }
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = !_isLegal;
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if(YesLeftTime.TotalSeconds>0||NoLeftTime.TotalSeconds > 0)
            {
                _timer = new DispatcherTimer();
                _timer.Interval = TimeSpan.FromSeconds(1);
                _timer.Tick += (S, E) =>
                {         
                    if (YesLeftTime.TotalSeconds > 0)
                    {
                        YesLeftTime = YesLeftTime.Add(-TimeSpan.FromSeconds(1));
                    }
                    else if (YesLeftTime.TotalSeconds == 0)
                    {
                        _timer.Stop();
                        Yes_Button_Click(null, null);
                    }
                    if (NoLeftTime.TotalSeconds > 0)
                    {
                        NoLeftTime = NoLeftTime.Add(-TimeSpan.FromSeconds(1));
                    }
                    else if (NoLeftTime.TotalSeconds == 0)
                    {
                        _timer.Stop();
                        No_Button_Click(null, null);
                    }
                };
                _timer.Start();
            }
        }
    }
}

二、效果预览

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

三、调用方法

是否按钮

var r = MessageBox.ShowDialog("确定?", "是", "否");
if (r.IsYes)
{
    //选择了Yes
}
else
{
    //选择了No
} 

OK按钮

MessageBox.ShowDialog("Ensure?", "OK", null);

Toast

MessageBox.Toast("确定?", TimeSpan.FromSeconds(3));

总结

在xaml使用了一些触发器,根据不同的按钮设置显示不同的样式,增加了MessageBox的功能,以及灵活性。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeOfCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值