3.设置消息对话框是否将触发源作为父窗体并显示遮罩层
<!-- 弹出提示窗体模板 --> <ControlTemplate x:Key="AlertDialogBaseTemplate" TargetType="{x:Type Window}"> <Border x:Name="border" Margin="0" Background="White" CornerRadius="3" RenderTransformOrigin="0.5,0.5"> <i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <helper:EventToCommand Command="{Binding LoadedCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" /> </i:EventTrigger> </i:Interaction.Triggers> <Border.RenderTransform> <TransformGroup> <ScaleTransform /> </TransformGroup> </Border.RenderTransform> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <toolkit:ImageButton Grid.Row="0" Width="16" Height="16" Margin="0,16,16,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Command="{Binding CloseWinCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" DownImage="Images/AlterDialog/btnclose_hover.png" HoverImage="Images/AlterDialog/btnclose_hover.png" NormalImage="Images/AlterDialog/btnclose.png" ToolTip="关闭" Visibility="{Binding DialogMode, Converter={helper:EnumExcludeConverter}, ConverterParameter='Mini'}" /> <ContentPresenter Grid.Row="1" /> </Grid> </Border> </ControlTemplate> <!-- 弹出提示窗体样式 --> <Style x:Key="AlterDailogBaseStyle" TargetType="{x:Type view:AlterDialogWindow}" BasedOn="{StaticResource BaseWindowStyle}"> <Setter Property="AllowsTransparency" Value="True" /> <Setter Property="Height" Value="180" /> <Setter Property="MaxHeight" Value="240" /> <Setter Property="MaxWidth" Value="400" /> <Setter Property="OverridesDefaultStyle" Value="True" /> <Setter Property="Template" Value="{StaticResource AlertDialogBaseTemplate}" /> <Setter Property="Topmost" Value="False" /> <Setter Property="Width" Value="400" /> <Setter Property="WindowState" Value="Normal" /> <Setter Property="WindowStyle" Value="None" /> </Style> <Style TargetType="{x:Type view:AlterDialogWindow}" BasedOn="{StaticResource AlterDailogBaseStyle}" />上述代码中,通过把WindowStyle属性设置为None来隐藏默认的非工作区(控制区),然后再窗口的Template中定义一个两行的Grid,第一行模拟窗口非工作区的标题栏,本例中仅放一个关闭按钮。第二行则是工作区。
<DataTemplate x:Key="TemplateMini"> <StackPanel Margin="40,15,40,15" HorizontalAlignment="Center" Orientation="Horizontal"> <StackPanel.Resources> <Style TargetType="{x:Type TextBlock}"> <Setter Property="FontSize" Value="18" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> <Style TargetType="{x:Type toolkit:SelectableTextBlock}"> <Setter Property="FontSize" Value="18" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> </StackPanel.Resources> <Image Width="32" Height="34" HorizontalAlignment="Right" RenderOptions.BitmapScalingMode="LowQuality" RenderOptions.CachingHint="Cache" SnapsToDevicePixels="False" Source="{Binding DialogType, Converter={StaticResource AlterDialogWindow_IconConverter}}" Stretch="UniformToFill" /> <ScrollViewer MaxWidth="300" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <toolkit:SelectableTextBlock Margin="0,0,0,0" HorizontalAlignment="Left" FontSize="18" Foreground="#333333" Text="{Binding Content}" TextWrapping="Wrap" /> </ScrollViewer> </StackPanel> </DataTemplate> <DataTemplate x:Key="TemplateNormal"> <StackPanel Margin="40,18,40,0" HorizontalAlignment="Center" VerticalAlignment="Top" Orientation="Horizontal"> <StackPanel.Resources> <Style TargetType="{x:Type TextBlock}"> <Setter Property="FontSize" Value="18" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> <Style TargetType="{x:Type toolkit:SelectableTextBlock}"> <Setter Property="FontSize" Value="18" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> </StackPanel.Resources> <Image Width="40" Height="42" HorizontalAlignment="Right" RenderOptions.BitmapScalingMode="LowQuality" RenderOptions.CachingHint="Cache" SnapsToDevicePixels="False" Source="{Binding DialogType, Converter={StaticResource AlterDialogWindow_IconConverter}}" Stretch="UniformToFill" /> <ScrollViewer MaxWidth="280" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <toolkit:SelectableTextBlock Margin="0,0,0,0" HorizontalAlignment="Left" FontSize="18" Foreground="#333333" Text="{Binding Content}" TextWrapping="Wrap" /> </ScrollViewer> </StackPanel> </DataTemplate> <DataTemplate x:Key="TemplateFull"> <Grid Margin="40,10,40,0" HorizontalAlignment="Center" VerticalAlignment="Top"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Image Width="54" Height="56" HorizontalAlignment="Center" RenderOptions.BitmapScalingMode="LowQuality" RenderOptions.CachingHint="Cache" SnapsToDevicePixels="False" Source="{Binding DialogType, Converter={StaticResource AlterDialogWindow_IconConverter}}" Stretch="UniformToFill" /> <ScrollViewer Grid.Row="1" MaxWidth="300" Margin="0,12,0,0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <StackPanel> <toolkit:SelectableTextBlock Margin="0,0,0,0" HorizontalAlignment="Center" FontSize="18" Foreground="#333333" Text="{Binding Content}" TextWrapping="Wrap" /> <toolkit:SelectableTextBlock HorizontalAlignment="Center" FontSize="14" Foreground="#999999" Text="{Binding SubContent}" /> </StackPanel> </ScrollViewer> </Grid> </DataTemplate>交互区域可定义两个模板:仅显示确定按钮,显示确定和取消按钮。
<DataTemplate x:Key="Template0"> <StackPanel Orientation="Horizontal"> <toolkit:ImageButton Width="108" Height="56" Command="{Binding YesCommand}" DownImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|2'}" Foreground="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|3'}" HoverImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|1'}" NormalImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|0'}"> <Grid> <TextBlock FontSize="16" Foreground="White" Text="{Binding YesButtonText}" Visibility="{Binding IsCountdown, Converter={StaticResource VisibilityConverter}, ConverterParameter='!'}" /> <StackPanel Orientation="Horizontal" TextBlock.Foreground="White" Visibility="{Binding IsCountdown, Converter={StaticResource VisibilityConverter}}"> <TextBlock FontSize="16" Text="{Binding YesButtonText}" /> <TextBlock FontSize="14" Text="{Binding Countdown, StringFormat={}({0}s)}" /> </StackPanel> </Grid> </toolkit:ImageButton> <toolkit:ImageButton Width="108" Height="32" Margin="29,0,0,0" Command="{Binding NoCommand}" DownImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='1|2'}" Foreground="#366d85" HoverImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='1|1'}" IsDefault="True" NormalImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='1|0'}"> <TextBlock FontSize="16" Foreground="#0099ff" Text="{Binding NoButtonText}" /> </toolkit:ImageButton> </StackPanel> </DataTemplate> <DataTemplate x:Key="Template1"> <StackPanel Orientation="Horizontal"> <toolkit:ImageButton Width="108" Height="56" Command="{Binding YesCommand}" DownImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|2'}" FontSize="18" Foreground="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|3'}" HoverImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|1'}" IsDefault="True" NormalImage="{Binding DialogType, Converter={StaticResource AlterDialogWindow_ButtonConverter}, ConverterParameter='0|0'}"> <Grid> <TextBlock FontSize="16" Foreground="White" Text="{Binding YesButtonText}" Visibility="{Binding IsCountdown, Converter={StaticResource VisibilityConverter}, ConverterParameter='!'}" /> <StackPanel Orientation="Horizontal" TextBlock.Foreground="White" Visibility="{Binding IsCountdown, Converter={StaticResource VisibilityConverter}}"> <TextBlock FontSize="16" Text="{Binding YesButtonText}" /> <TextBlock FontSize="14" Text="{Binding Countdown, StringFormat={}({0}s)}" /> </StackPanel> </Grid> </toolkit:ImageButton> </StackPanel> </DataTemplate>定义好了信息区域和交互区域的几种模板后,AlterDialogWindow声明两个ContentPresenter表示信息区域和交互区域,通过模板选择器选择相应模板。其中交互区域通过绑定对话框类型来判断是否显示该区域。
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Top" Content="{Binding}"> <ContentPresenter.ContentTemplateSelector> <local:AlterDialogWindowContentTemplateSelector Template0="{StaticResource TemplateMini}" Template1="{StaticResource TemplateNormal}" Template2="{StaticResource TemplateFull}" /> </ContentPresenter.ContentTemplateSelector> </ContentPresenter> <ContentPresenter Grid.Row="1" Margin="0,0,0,16" HorizontalAlignment="center" VerticalAlignment="Top" Content="{Binding}" Visibility="{Binding DialogMode, Converter={helper:EnumExcludeConverter}, ConverterParameter='Mini'}"> <ContentPresenter.ContentTemplateSelector> <local:AlterDialogWindowButtonDataTemplateSelector Template0="{StaticResource Template0}" Template1="{StaticResource Template1}" /> </ContentPresenter.ContentTemplateSelector> </ContentPresenter> </Grid>至此,一个消息对话框就基本完成了。前边确定功能时提到调用消息对话框的窗口显示遮罩层。针对这个功能,我们可以在AlterDialogWindow中定义一个ShowDialog方法,参数是调用消息对话框的窗口对象,然后在该窗口中加上一个半透明的Grid作为遮罩层,并在AlterDialogWindow的OnClosed事件处理逻辑中删除遮罩层。
public bool? ShowDialog(DependencyObject parent) { if (this.Parent == null && parent != null) { // 堆代码 duidaima.com Grid layer = new Grid() { Name = "maskLayer", Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)) }; _grid = Window.GetWindow(parent).FindFirstVisualChild<Grid>(); if (_grid.FindAllVisualChilds<Grid>().FirstOrDefault(r => r.Name == "maskLayer") == null) _grid.Children.Add(layer); if (_grid.RowDefinitions.Count > 0) Grid.SetRowSpan(layer, _grid.RowDefinitions.Count); if (_grid.ColumnDefinitions.Count > 0) Grid.SetColumnSpan(layer, _grid.ColumnDefinitions.Count); this.Owner = Window.GetWindow(parent); this.WindowStartupLocation = WindowStartupLocation.CenterOwner; } return ShowDialog(); }小结