ChildWindow:Popup的加强版

Silverlight项目中少不了弹出窗口,Silverlight中提供了ChildWindow作为弹出窗口,已经能满足大部分需求。 但是ChildWindow模板并不好看,而且位置总是居中,很难通过Transform来控制。为了进一步了解ChildWindow控件,我反编译了ChildWindow的源代码,一探究竟。发现ChildWindow其实可以很强大。 

ChildWindow的默认模板示例:

 

代码
<ControlTemplate TargetType="controls:ChildWindow">
<Grid x:Name="Root">
<Grid x:Name="Overlay" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0" Background="{TemplateBinding OverlayBrush}" Opacity="{TemplateBinding OverlayOpacity}" />
<Grid x:Name="ContentRoot" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" RenderTransformOrigin="0.5,0.5" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
<Border CornerRadius="1.5" Margin="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Border x:Name="Chrome" Width="Auto" BorderBrush="#FFFFFFFF" BorderThickness="0,0,0,1">
<Grid Height="Auto" Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<ContentControl Content="{TemplateBinding Title}" IsTabStop="False" FontWeight="Bold" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="6,0,6,0" />
<Button x:Name="CloseButton" Grid.Column="1" IsTabStop="False" HorizontalAlignment="Center" VerticalAlignment="Center" Width="15" Height="14" Style="{StaticResource ButtonStyle}" />
</Grid>
</Border>
<Border Background="{TemplateBinding Background}" Margin="7" Grid.Row="1">
<ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Grid>
</Border>
</Border>
</Grid>
</Grid>
</ControlTemplate>

 

 

C#代码示例:

 

public void Show()
{
if (this.ChildWindowPopup == null)
{
this.ChildWindowPopup = new Popup();
try
{
this.ChildWindowPopup.Child = this;
}
catch (ArgumentException)
{
this.InteractionState = WindowInteractionState.NotResponding;
throw new InvalidOperationException(Resources.ChildWindow_InvalidOperation);
}
}
if ((this.ChildWindowPopup != null) && (Application.Current.RootVisual != null))
{
this.ChildWindowPopup.IsOpen = true;
this._dialogresult = null;
}
if (RootVisual != null)
{
RootVisual.IsEnabled
= false;
}
}

 

 

 

从模板和C#代码中,我们可以看到ChildWindow是用Popup来显示的,Overlay元素为背景,ContentRoot就是我们看到的弹出框的,Chrome作为弹出框头部。我们自定义的内容放在ContentPresenter中,掌握了ChildWindow的实现和模板后,我们就可以任意定制自己的弹出窗口了,改变弹出窗口的模板,并添加我们想要的功能。

 

默认的弹出框总是居中,如何改变弹出框位置呢? 我们可以在自定义的弹出框中重载OnApplyTemplate来给ContentRoot添加变换。

在这里我们还可以附加其他功能,如点击弹出框以外的部分时,让弹出框关闭等。示例代码如下。

 

public override void OnApplyTemplate()
{
base.OnApplyTemplate();


Overlay
= this.GetTemplateChild("Overlay") as Panel;
if (Overlay != null)
{
Overlay.MouseLeftButtonDown
+= new MouseButtonEventHandler(Overlay_MouseLeftButtonDown);
}

TranslateTransform translate
= new TranslateTransform();
translate.X
= Left;
translate.Y
= Top;

TransformGroup renderTransform
= this.ContentRoot.RenderTransform as TransformGroup;
if (renderTransform != null)
{
renderTransform.Children.Add(translate);
}
else
{
this.ContentRoot.RenderTransform = translate;
}
}
posted @ 2010-09-06 11:12  DevinShaw  阅读(2787)  评论(2编辑  收藏  举报