C# wpf 实现自定义界面操作分离的MessageBox

WPF 自定义MessageBox系列

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



前言

本篇是上一篇《C# wpf 实现自定义按钮及Toast的MessageBox》的优化,将MessageBox的操作逻辑与界面完全分离了,这样做的好处是在于,界面的随意切换,操作逻辑可以不用改动或重写。


一、如何分离?

1、定义DataContext对象

定义一个DataContext对象,将需要的数据全部定义在DataContext对象中,通过INotifyPropertyChanged实现双向通知。
MessageBox需要的属性有:

/// <summary>
/// 消息框的标题
/// </summary>
public string Title{get;get;}
/// <summary>
/// 消息框的文本内容
/// </summary>
public string Context{get;get;}
/// <summary>
/// Yes按钮的文本
/// </summary>
public string YesText{get;get;}
/// <summary>
/// No按钮的文本
/// </summary>
public string NoText{get;get;}
/// <summary>
/// Yes选项剩余时间
/// </summary>
public TimeSpan? YesLeftTime{get;get;}
/// <summary>
/// No选项剩余时间
/// </summary>
public TimeSpan? NoLeftTime{get;get;}
/// <summary>
/// No按钮命令
/// </summary>
public ICommand NoCommand{get;get;}
/// <summary>
/// Yes按钮命令
/// </summary>
public ICommand YesCommand{get;get;}
/// <summary>
///Cancel按钮命令
/// </summary>
public ICommand CancelCommand{get;get;}

2、绑定属性

在xaml中实现消息框的样式,并绑定上述属性。上述属性不需要全部绑定可以根据需要自行选择,比如只需要定义一个Toast则只绑定Context即可。

<TextBlock  Text="{Binding Context}" />

3、泛型调用

将MessageBox的操作方法定义成泛型,根据具体传入的MessageBox与DataContext对象关联后再显示。比如将方法定义在MessageBoxHelper类中:
MessageBox窗口

 MessageBoxHelper.ShowDialog<MessageBox>("Ensure?", "Yes", "No",TimeSpan.FromSeconds(10), null);

Toast窗口

 MessageBoxHelper.Toast<Toast>("Hello word",TimeSpan.FromSeconds(10));

二、代码

1、接口设计

代码的逻辑关系:
在这里插入图片描述
上图对应到代码:
在这里插入图片描述

将所有操作逻辑封装在MessageBoxHelper中:

namespace WpfApp1
{
    /// <summary>
    /// 结果按钮
    /// </summary>
    public enum MessageBoxResultButton
    {
        Yes,
        No,
        Cancel
    }
    /// <summary>
    /// 结果
    /// </summary>
    public class MessageBoxResult
    {
        /// <summary>
        /// 结果按钮
        /// </summary>
        public MessageBoxResultButton Button { get; set; }
        /// <summary>
        /// Yes剩余时间
        /// </summary>
        public TimeSpan? YesLeftTime { get; set; }
        /// <summary>
        /// No剩余时间
        /// </summary>
        public TimeSpan? NoLeftTime { get; set; }
    }
    /// <summary>
    /// 业务数据对象
    /// </summary>
    public class MessageBoxDataContext : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// 消息框的标题
        /// </summary>
        public string Title{ set; get; }

        /// <summary>
        /// 消息框的文本内容
        /// </summary>
        public string Context{ set; get; }

        /// <summary>
        /// Yes按钮的文本
        /// </summary>
        public string YesText{ set; get; }

        /// <summary>
        /// No按钮的文本
        /// </summary>
        public string NoText{ set; get; }

        /// <summary>
        /// Yes选项剩余时间
        /// </summary>
        public TimeSpan? YesLeftTime{ set; get; }

        /// <summary>
        /// No选项剩余时间
        /// </summary>
        public TimeSpan? NoLeftTime{ set; get; }

        /// <summary>
        /// No按钮命令
        /// </summary>
        public ICommand NoCommand{ set; get; }

        /// <summary>
        /// Yes按钮命令
        /// </summary>
        public ICommand YesCommand{ set; get; }

        /// <summary>
        ///Cancel按钮命令
        /// </summary>
        public ICommand CancelCommand{ set; get; }

        /// <summary>
        ///结果
        /// </summary>
        public MessageBoxResult Result { internal set; get; }

 
    }

    public class MessageBoxHelper
    {
        /// <summary>
        ///toast弹出消息
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <param name="stayTime">停留时间</param>
        public static void Toast<T>(string context, TimeSpan stayTime) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string context) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context) where T : Window, new();

        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context, string yesText) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="isCancelable">是否显示取消按钮</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context, string yesText, bool isCancelable) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context, string yesText, string noText) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="isCancelable">是否显示取消按钮</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context, string yesText, string noText, bool isCancelable) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string context, TimeSpan? yestCountDown, TimeSpan? noCountDown) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string context, string yesText, string noText, TimeSpan? yestCountDown, TimeSpan? noCountDown) where T : Window, new();
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context, string yesText, string noText, TimeSpan? yestCountDown, TimeSpan? noCountDown) where T : Window, new();
        /// 显示消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <param name="isCancelable">是否显示取消按钮</param>
        /// <returns>结果</returns>
        public static MessageBoxResult ShowDialog<T>(string title, string context, string yesText, string noText, TimeSpan? yestCountDown, TimeSpan? noCountDown, bool isCancelable) where T : Window, new();
        /// <summary>
        /// 获取结果,通常和MessageBoxHelper.Create<T>配合使用
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="messageBox">MessageBoxHelper.Create<T>返回的对象</param>
        /// <returns>结果</returns>
        public static MessageBoxResult GetResult<T>(T messageBox) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string context) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string title, string context) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string title, string context, string yesText) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="isCancelable">是否显示取消按钮</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string title, string context, string yesText, bool isCancelable) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string title, string context, string yesText, string noText) where T : Window, new();

        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="isCancelable">是否显示取消按钮</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string title, string context, string yesText, string noText, bool isCancelable) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string context, TimeSpan? yestCountDown, TimeSpan? noCountDown) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string context, string yesText, string noText, TimeSpan? yestCountDown, TimeSpan? noCountDown) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <returns>消息框对象</returns>
        public static T Createg<T>(string title, string context, string yesText, string noText, TimeSpan? yestCountDown, TimeSpan? noCountDown) where T : Window, new();
        /// <summary>
        /// 创建消息框
        /// </summary>
        /// <typeparam name="T">绑定MessageBoxDataContext属性的窗口</typeparam>
        /// <param name="title">标题</param>
        /// <param name="context">显示内容</param>
        /// <param name="yesText">yes按钮的文本</param>
        /// <param name="noText">no按钮的文本</param>
        /// <param name="yestCountDown">yes按钮倒计时</param>
        /// <param name="noCountDown">no按钮倒计时</param>
        /// <param name="isCancelable">是否显示取消按钮</param>
        /// <returns>消息框对象</returns>
        public static T Create<T>(string title, string context, string yesText, string noText, TimeSpan? yestCountDown, TimeSpan? noCountDown, bool isCancelable) where T : Window, new();
       
    }
}

2、完整代码

https://download.csdn.net/download/u013113678/85477733


三、实例

1、Toast

(1)界面代码

<Window x:Class="WpfApp1.Toast"
        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="Toast"
        AllowsTransparency="True"
        Background="Transparent"
        ResizeMode="NoResize"
        ShowInTaskbar="False"
        Topmost="True"
        WindowStartupLocation="CenterScreen"
        Width="400"
        Height="120"
        WindowStyle="None"              
        >
    <Grid>
        <Border  Margin="10" Background="White"  CornerRadius="10"  >
            <Border.Effect>
                <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.5"/>
            </Border.Effect>
            <Grid Margin="20">
                <StackPanel VerticalAlignment="Center">
                    <!--只需绑定Context-->
                    <TextBlock   Text="{Binding Context}"    HorizontalAlignment="Center"  VerticalAlignment="Center" FontSize="48"  Foreground="Gray"/>
                </StackPanel>
            </Grid>
        </Border>
    </Grid>
</Window>

(2)调用方法

MessageBoxHelper.Toast<Toast>("Hello word!", TimeSpan.FromSeconds(3));

(3)效果预览

在这里插入图片描述

2、简单MessageBox

(1)界面代码

<Window x:Class="WpfApp1.MessageBoxSimple"
        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="MessageBoxSimple"
        AllowsTransparency="True"
        Background="Transparent"
        ResizeMode="NoResize"
        ShowInTaskbar="False"
        Topmost="True"
        WindowStartupLocation="CenterScreen"
        Width="600"
        Height="260"
        WindowStyle="None">
    <Grid>
        <Border  Margin="10" Background="White"    >
            <Border.Effect>
                <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.5"/>
            </Border.Effect>
            <Grid Margin="20">
                <!--绑定Context-->
                <TextBlock  Margin="0,0,0,40" Text="{Binding Context}"    HorizontalAlignment="Center"  VerticalAlignment="Center" FontSize="48"  Foreground="Gray"/>
                <StackPanel VerticalAlignment="Bottom"  Orientation="Horizontal" HorizontalAlignment="Center" >
                    <!--绑定NoCommand命令-->
                    <Button  Height="64" Width="144"    Cursor="Hand"   Command="{Binding NoCommand}">
                        <Button.Template>
                            <ControlTemplate  TargetType="{x:Type Button}">
                                <Border   Background="White"  BorderBrush="#cccccc"  >
                                    <Border.Effect>
                                        <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.2"/>
                                    </Border.Effect>
                                    <!--绑定no文本NoText,也可以不绑定,直接使用页面上的文本-->
                                    <TextBlock  Name="text" Text="{Binding NoText}"   FontSize="24"    Foreground="Gray"  HorizontalAlignment="Center" VerticalAlignment="Center">
                                    </TextBlock>
                                </Border>
                            </ControlTemplate>
                        </Button.Template>
                    </Button>
                    <!--绑定YesCommand命令-->
                    <Button  Margin="30,0,0,0"  Height="64" Width="144"    Cursor="Hand"  Command="{Binding YesCommand}">
                        <Button.Template>
                            <ControlTemplate  TargetType="{x:Type Button}">
                                <Border  Background="Gray"  >
                                    <Border.Effect>
                                        <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.2"/>
                                    </Border.Effect>
                                    <!--绑定yes文本YesText,也可以不绑定,直接使用页面上的文本-->
                                    <TextBlock  Name="text"  Text="{Binding YesText}" FontSize="24"   Foreground="White"  HorizontalAlignment="Center" VerticalAlignment="Center">
                                    </TextBlock>
                                </Border>
                            </ControlTemplate>
                        </Button.Template>
                    </Button>
                </StackPanel>
            </Grid>
        </Border>
    </Grid>
</Window>

(2)调用方法

var r = MessageBoxHelper.ShowDialog<MessageBoxSimple>(null,"Ensure?", "Yes", "No");
if (r.Button == MessageBoxResultButton.Yes)
{
    //选择了Yes
}
else if (r.Button == MessageBoxResultButton.No)
{
    //选择了No
}

(3)效果预览

在这里插入图片描述

3、完整MessageBox

(1)界面代码

略,在完整代码中。

(2)调用方法及效果预览

Toast框

 MessageBoxHelper.Toast<MessageBox>("Toast框", TimeSpan.FromSeconds(3));

在这里插入图片描述

OK框

MessageBoxHelper.ShowDialog<MessageBox>(null, "OK框", "OK");

在这里插入图片描述

OK倒计时框

MessageBoxHelper.ShowDialog<MessageBox>(null, "OK倒计时框", "OK", null, TimeSpan.FromSeconds(10), null);

在这里插入图片描述

YesNo框

var r=MessageBoxHelper.ShowDialog<MessageBox>(null, "YesNo框", "Yes", "No");
if (r.Button == MessageBoxResultButton.Yes)
{
    //选择了Yes
}
else if (r.Button == MessageBoxResultButton.No)
{
    //选择了No
}

在这里插入图片描述

YesNo倒计时框

var r=MessageBoxHelper.ShowDialog<MessageBox>(null, "YesNo倒计时框", "Yes", "No", TimeSpan.FromSeconds(10),null);
if (r.Button == MessageBoxResultButton.Yes)
{
    //选择了Yes
}
else if (r.Button == MessageBoxResultButton.No)
{
    //选择了No
}

在这里插入图片描述
带标题栏OK框

 MessageBoxHelper.ShowDialog<MessageBox>("标题", "带标题栏OK框", "OK",null);

在这里插入图片描述

带标题栏YesNo框

var r=MessageBoxHelper.ShowDialog<MessageBox>("标题", "带标题栏YesNo框", "Yes", "No");
if (r.Button == MessageBoxResultButton.Yes)
{
    //选择了Yes
}
else if (r.Button == MessageBoxResultButton.No)
{
    //选择了No
}

在这里插入图片描述

可关闭YesNo框

var r=MessageBoxHelper.ShowDialog<MessageBox>("标题", "可关闭YesNo框", "Yes", "No", true);
if (r.Button == MessageBoxResultButton.Yes)
{
    //选择了Yes
}
else if (r.Button == MessageBoxResultButton.No)
{
    //选择了No

}
else if (r.Button == MessageBoxResultButton.Cancel)
{
    //关闭了窗口
}

在这里插入图片描述

可关闭倒计时框

var r=MessageBoxHelper.ShowDialog<MessageBox>("标题", "可关闭倒计时框", "Yes", "No", null, TimeSpan.FromSeconds(10), true);
if (r.Button == MessageBoxResultButton.Yes)
{
    //选择了Yes
}
else if (r.Button == MessageBoxResultButton.No)
{
    //选择了No
}
else if (r.Button == MessageBoxResultButton.Cancel)
{
    //关闭了窗口
}

在这里插入图片描述


总结

操作与界面分离后,方便了界面的灵活设计,在不同的项目只需要定义MessageBox的界面即可,操作逻辑直接使用MessageBoxHelper,减少了造轮子。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CodeOfCC

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

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

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

打赏作者

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

抵扣说明:

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

余额充值