原文:《模拟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 /// <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}" .../>
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 }
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>
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】