原文:《模拟MessageBox》 Posted on 2014/01/07

================================================================================

这段时间在用WPF开发项目。界面采用的是类似Win8系统的Metro风格,但是系统自带MessageBox貌似不能被Style,于是重写MessageBox。

之前一直没有写过自定义控件,就不知道怎么下手。于是从网上找了好些资料,发现了这篇博文《WPF 自定义 MessageBox (相对完善版)》。看了代码解释并运行了Demo,觉得根据实际需要改造下应该可以用到项目里来。

以前一直很好奇为什么能Style很多控件,而MessageBox却不能Style,查过.NET Reflector,发现:

public sealed class MessageBox : System.Object

MessageBox类 是直接继承自Object类,实际上是对具体细节进行了封装。

总体结构建立在Vito.K的代码基础之上,我加入的一些功能:

  1. 关闭按钮:
    在MessageBoxModule中定义关闭命令的依赖项属性:

     /// <summary>
    /// 关闭命令
    /// </summary>
    public static readonly DependencyProperty CloseCommandProperty =
    DependencyProperty.Register(
    "CloseCommand",
    typeof(RoutedCommand),
    typeof(MessageBoxModule));
     /// <summary>
    /// 关闭命令
    /// </summary>
    public RoutedCommand CloseCommand
    {
    get { return (RoutedCommand)GetValue(CloseCommandProperty); }
    set { SetValue(CloseCommandProperty, value); }
    }

    设置方法:

     /// <summary>
    /// 设置关闭窗口命令
    /// </summary>
    private void SetupCloseCommand()
    {
    InputGestureCollection inputGestures =
    new InputGestureCollection();
    inputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt)); CloseCommand = new RoutedCommand(
    "CloseCommand",
    typeof(MessageBoxModule),
    inputGestures); CommandBindings.Add(
    new CommandBinding(CloseCommand, CloseCommandExecuted));
    }

    在public MessageBoxModule()方法中调用即可。
    在MessageBoxModule的Style文件中对该命令的使用:

    <Button x:Name="CloseButton" Command="{TemplateBinding CloseCommand}" .../>
  2. 通过标题栏拖动MessageBox:
    之前写过的无边框的Windows窗体都是通过Rectangle的MouseLeftButtonDown事件来触发拖动窗体的,然后这个方法在这边行不通,于是又用这方法,还是行不通: 
     <i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseLeftButtonDown">
    <i:InvokeCommandAction Command="{TemplateBinding DragOverCommand}"/>
    </i:EventTrigger/>
    </i:Interaction.Triggers>

    无意间看到《WPF编程宝典 C# 2010版》第18章中的无外观控件代码中的TemplatePart。照猫画虎地写下了以下代码:
    在Style文件中:

    <Rectangle x:Name="PART_TitleRectangle" .../>

    在MessageBoxModule类中:
    在类前面加上:

     [TemplatePart(Name="PART_TitleRectangle", Type=typeof(Rectangle))]
    internal sealed class MessageBoxModule : Window
    { }

    重载public void OnApplyTemplate()方法:

     public override void OnApplyTemplate()
    {
    base.OnApplyTemplate(); // 为TitleRectangle添加MouseLeftButtonDown事件处理程序
    Rectangle rect = GetTemplateChild("PART_TitleRectangle") as Rectangle;
    if (rect != null)
    {
    rect.MouseLeftButtonDown += (sender, e) => { DragMove(); };
    }
    }
  3. 显示详细信息:
    主要是Style中几个相关控件的Visibility的设置,依据是MessageBoxModule类中的指定值,即DependencyProperty MessageDetailProperty是否为空来选择是否启用显示相信信息功能:
     <DockPanel x:Name="RootLayoutPanel">
    ...
    <Separator Visibility="{Binding Path=Visibility, ElementName=MessageDetailTextBlock}" DockPanel.Dock="Bottom"/>
    <!--信息区-->
    <DockPanel x:Name="ContentDockPanel" DockPanel.Dock="Top">
    ...
    <TextBlock x:Name="MessageTextBlock" Text="{TemplateBinding Message}" DockPanel.Dock="Top" />
    <Grid Visibility="{Binding Path=IsChecked, ElementName=DetailInfoToggleButton, Converter={converter:BooleanToVisibilityConverter}}" >
    <TextBlock x:Name="MessageDetailTextBlock"
    Text="{TemplateBinding MessageDetail}"
    Visibility="{TemplateBinding MessageDetail, Converter={converter:StringToVisibilityConverter}}"
    DockPanel.Dock="Bottom" />
    </Grid>
    </DockPanel>
    </DockPanel>
  4. 加入MessageBoxImage:
    通过MessageBoxModule类中的DependencyProperty MessageBoxIconTypeProperty来指定显示哪种类型的图片: 
     /// <summary>
    /// 消息框图标
    /// </summary>
    public static readonly DependencyProperty MessageBoxIconTypeProperty =
    DependencyProperty.Register(
    "MessageBoxIconType",
    typeof(MessageBoxIcon),
    typeof(MessageBoxModule),
    new PropertyMetadata(MessageBoxIcon.None));

    MessageBoxIcon是枚举类型类似于MessageBoxImage的一个枚举类型:

     /// <summary>
    /// 图标
    /// </summary>
    public enum MessageBoxIcon
    {
    None = ,
    Error = 0x10,
    //Hand = 0x10,
    //Stop = 0x10,
    Question = 0x20,
    Warning = 0x30,
    //Exclamation = 0x30,
    //Asterisk = 0x40,
    //Information = 0x40,
    }

    在Style文件中:

     <!--信息区-->
    <DockPanel x:Name="ContentDockPanel" DockPanel.Dock="Top" Margin="15,10">
    <Image x:Name="MB_MistakeImage" Visibility="Collapsed" Source="/Controls;component/Images/messagebox_mistake.png"/>
    <Image x:Name="MB_QueryImage" Visibility="Collapsed" Source="/Controls;component/Images/messagebox_query.png"/>
    <Image x:Name="MB_WarningImage" Visibility="Collapsed" Source="/Controls;component/Images/messagebox_warning.png"/>
    ...
    </DockPanel>

    用ControlTemplate.Triggers进行控制对应Image的Visibility属性:

     <ControlTemplate.Triggers>
    <Trigger Property="MessageBoxIconType" Value="Error">
    <Setter Property="Visibility" TargetName="MB_MistakeImage" Value="Visible"/>
    </Trigger>
    <Trigger Property="MessageBoxIconType" Value="Question">
    <Setter Property="Visibility" TargetName="MB_QueryImage" Value="Visible"/>
    </Trigger>
    <Trigger Property="MessageBoxIconType" Value="Warning">
    <Setter Property="Visibility" TargetName="MB_WarningImage" Value="Visible"/>
    </Trigger>
    </ControlTemplate.Triggers>

【END】

模拟MessageBox的更多相关文章

  1. WPF 自定义 MessageBox (相对完善版)

    WPF 自定义 MessageBox (相对完善版)     基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ...

  2. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)

    基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...

  3. ASP.NET中MessageBox的实现

    asp.net中没有MessageBox这个控件,固然可以插入Winform里的MessageBox,但一般不提倡,所以只能变通实现,主要有这几种方法: 1.直接利用javascript的alert和 ...

  4. C语言嵌入式系统编程修炼之四:屏幕操作

    汉字处理 现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能.例如,一个微波炉的LCD上没有必要提供显示"电子邮件"的功 ...

  5. C语言嵌入式系统编程修炼

    C语言嵌入式系统编程修炼 2008-08-19 作者:宋宝华 来源:天极网 C语言嵌入式系统编程修炼之背景篇 本文的讨论主要围绕以通用处理器为中心的协议处理模块进行,因为它更多地牵涉到具体的C语言编程 ...

  6. [读书笔记2]《C语言嵌入式系统编程修炼》

    第3章 屏幕操作   3.1 汉字处理 现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能.例如,一个微波炉的LCD上没有必要提供显示&qu ...

  7. c# winform 自动关闭messagebox 模拟回车

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  8. 一个简单的Webservice的demo,简单模拟服务

    前段时间一直在学习WCF,匆匆忙忙的把<WCF全面解析>和<WCF服务编程>看了一遍,好多东西都不是很懂,又听了一下WCF分布式开发的网络教程,算是马马虎虎的明白点了.回顾了一 ...

  9. NetworkComms V3 模拟登陆

    演示NetworkComms V3的用法 例子很简单 界面如下: 服务器端代码: 开始监听: //服务器开始监听客户端的请求 Connection.StartListening(ConnectionT ...

随机推荐

  1. java获取静态页面内容

    package collection_map; import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.F ...

  2. Oracle数据库恢复

    建用户 wf2014 赋权限 grant dba to wf2014; 数据恢复 imp wf2014/wf2014 file=D:\wf2014.dmp full=y 参数设置: datasourc ...

  3. 使用 multiprocessing.dummy 执行多线程任务

    # -*- coding: utf-8 -*- # from multiprocessing import Pool 多进程 from multiprocessing.dummy import Poo ...

  4. 騰訊RTX的API開發,給RTX開個天窗

    好多人可能沒聽說RTX這個軟件,在此我簡單說明一下,這個軟件是騰訊為企業開發的一個內部聊天軟件,服務端不是在騰訊那邊,而是需要企業自己安裝到自己公司內部的服務器上,以供企業內部員工交流使用,功能和QQ ...

  5. 转:Hide data inside pointers(在指针中隐藏数据)

    该文介绍了如何使用指针中一些未使用的位来隐藏一些数据. When we write C code, pointers are everywhere. We can make a little extr ...

  6. 15个最好的PDF转word的在线转换器,将PDF文件转换成doc文件

    PDF是一种文件格式,包含文本,图像,数据等,这是独立于操作系统的文件类型.它是一个开放的标准,压缩,另一方面DOC文件和矢量图形是由微软文字处理文件.该文件格式将纯文本格式转换为格式化文档.它支持几 ...

  7. LeetCode:Longest Substring Without Repeating Characters(最长不重复子串)

    题目链接 Given a string, find the length of the longest substring without repeating characters. For exam ...

  8. blueImp/jQuery file upload 的正确用法(限制上传大小和文件类型)

    这个插件太出名了,几乎能完成所有能想象的到的效果,包括进度条.拖拽.甚至现在已经完美支持图片视频等的处理,三个字形容就是屌爆了.最近在做上传这一部分,发现网上对于上传文件大小的限制和类型检测等的方法都 ...

  9. 极简MVC的实现

    我们来打造一个简单的专用于json调用的mvc实现,最终会将如下的C#代码暴露给js调用(代码在最后面有下载): public class UserController { public static ...

  10. XE6 FMX之控件绘制与显示

    中午,有个货随手买的2块钱的彩票,尼玛中了540块,这是啥子狗屎气运.稍微吐槽一下,现在开始正规的笔记录入.经常有朋友说为毛我的博客不更新了或者说更新的少了,为啥呢!一来自己懒了,没学习什么新的东西, ...