模擬MessageBox

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

================================================================================編程

這段時間在用WPF開發項目。界面採用的是相似Win8系統的Metro風格,可是系統自帶MessageBox貌似不能被Style,因而重寫MessageBox。windows

以前一直沒有寫過自定義控件,就不知道怎麼下手。因而從網上找了好些資料,發現了這篇博文《WPF 自定義 MessageBox (相對完善版)》。看了代碼解釋並運行了Demo,以爲根據實際須要改造下應該能夠用到項目裏來。ide

之前一直很好奇爲何能Style不少控件,而MessageBox卻不能Style,查過.NET Reflector,發現:spa

public sealed class MessageBox : System.Object

MessageBox類 是直接繼承自Object類,其實是對具體細節進行了封裝。code

整體結構創建在Vito.K的代碼基礎之上,我加入的一些功能:component

  1. 關閉按鈕:
    在MessageBoxModule中定義關閉命令的依賴項屬性: 
    1 /// <summary>
    2 /// 關閉命令
    3 /// </summary>
    4 public static readonly DependencyProperty CloseCommandProperty =
    5     DependencyProperty.Register(
    6         "CloseCommand", 
    7         typeof(RoutedCommand), 
    8         typeof(MessageBoxModule));
    1 /// <summary>
    2 /// 關閉命令
    3 /// </summary>
    4 public RoutedCommand CloseCommand
    5 {
    6     get { return (RoutedCommand)GetValue(CloseCommandProperty); }
    7     set { SetValue(CloseCommandProperty, value); }
    8 }

    設置方法:orm

     1 /// <summary>
     2 /// 設置關閉窗口命令
     3 /// </summary>
     4 private void SetupCloseCommand()
     5 {
     6     InputGestureCollection inputGestures = 
     7         new InputGestureCollection();
     8     inputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));
     9 
    10     CloseCommand = new RoutedCommand(
    11         "CloseCommand",
    12         typeof(MessageBoxModule),
    13         inputGestures);
    14 
    15     CommandBindings.Add(
    16         new CommandBinding(CloseCommand, CloseCommandExecuted));
    17 }

    在public MessageBoxModule()方法中調用便可。
    在MessageBoxModule的Style文件中對該命令的使用:htm

    <Button x:Name="CloseButton" Command="{TemplateBinding CloseCommand}" .../>
  2. 經過標題欄拖動MessageBox:
    以前寫過的無邊框的Windows窗體都是經過Rectangle的MouseLeftButtonDown事件來觸發拖動窗體的,而後這個方法在這邊行不通,因而又用這方法,仍是行不通: 
    1 <i:Interaction.Triggers>
    2     <i:EventTrigger EventName="MouseLeftButtonDown">
    3         <i:InvokeCommandAction Command="{TemplateBinding DragOverCommand}"/>
    4     </i:EventTrigger/>
    5 </i:Interaction.Triggers>

    無心間看到《WPF編程寶典 C# 2010版》第18章中的無外觀控件代碼中的TemplatePart。照貓畫虎地寫下了如下代碼:
    在Style文件中:blog

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

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

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

    重載public void OnApplyTemplate()方法:

     1 public override void OnApplyTemplate()
     2 {
     3     base.OnApplyTemplate();
     4 
     5     // 爲TitleRectangle添加MouseLeftButtonDown事件處理程序
     6     Rectangle rect = GetTemplateChild("PART_TitleRectangle") as Rectangle;
     7     if (rect != null)
     8     {
     9         rect.MouseLeftButtonDown += (sender, e) => { DragMove(); };
    10     }
    11 }
  3. 顯示詳細信息:
    主要是Style中幾個相關控件的Visibility的設置,依據是MessageBoxModule類中的指定值,即DependencyProperty MessageDetailProperty是否爲空來選擇是否啓用顯示相信信息功能:
     1 <DockPanel x:Name="RootLayoutPanel">
     2     ...
     3     <Separator Visibility="{Binding Path=Visibility, ElementName=MessageDetailTextBlock}" DockPanel.Dock="Bottom"/>
     4     <!--信息區-->
     5     <DockPanel x:Name="ContentDockPanel" DockPanel.Dock="Top">
     6         ...
     7         <TextBlock x:Name="MessageTextBlock" Text="{TemplateBinding Message}"  DockPanel.Dock="Top" />
     8         <Grid Visibility="{Binding Path=IsChecked, ElementName=DetailInfoToggleButton, Converter={converter:BooleanToVisibilityConverter}}" >
     9             <TextBlock x:Name="MessageDetailTextBlock" 
    10                 Text="{TemplateBinding MessageDetail}" 
    11                 Visibility="{TemplateBinding MessageDetail, Converter={converter:StringToVisibilityConverter}}" 
    12                 DockPanel.Dock="Bottom" />
    13         </Grid>
    14     </DockPanel>
    15 </DockPanel>
  4. 加入MessageBoxImage:
    經過MessageBoxModule類中的DependencyProperty MessageBoxIconTypeProperty來指定顯示哪一種類型的圖片: 
    1 /// <summary>
    2 /// 消息框圖標
    3 /// </summary>
    4 public static readonly DependencyProperty MessageBoxIconTypeProperty =
    5     DependencyProperty.Register(
    6         "MessageBoxIconType",
    7         typeof(MessageBoxIcon),
    8         typeof(MessageBoxModule),
    9         new PropertyMetadata(MessageBoxIcon.None));

    MessageBoxIcon是枚舉類型相似於MessageBoxImage的一個枚舉類型:

     1 /// <summary>
     2 /// 圖標
     3 /// </summary>
     4 public enum MessageBoxIcon
     5 {
     6     None = 0,
     7     Error = 0x10,
     8     //Hand = 0x10,
     9     //Stop = 0x10,
    10     Question = 0x20,
    11     Warning = 0x30,
    12     //Exclamation = 0x30,
    13     //Asterisk = 0x40,
    14     //Information = 0x40,
    15 }

    在Style文件中:

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

    用ControlTemplate.Triggers進行控制對應Image的Visibility屬性:

     1 <ControlTemplate.Triggers>
     2     <Trigger Property="MessageBoxIconType" Value="Error">
     3         <Setter Property="Visibility" TargetName="MB_MistakeImage" Value="Visible"/>
     4     </Trigger>
     5     <Trigger Property="MessageBoxIconType" Value="Question">
     6         <Setter Property="Visibility" TargetName="MB_QueryImage" Value="Visible"/>
     7     </Trigger>
     8     <Trigger Property="MessageBoxIconType" Value="Warning">
     9         <Setter Property="Visibility" TargetName="MB_WarningImage" Value="Visible"/>
    10     </Trigger>
    11 </ControlTemplate.Triggers>

【END】

相關文章
相關標籤/搜索