文档下载:http://www.ctdisk.com/file/1758325
ChildWindow在所有应用领域中都是必不可缺的好工具,小到一个弹出的确认对话框;大到包含众多复杂参数、选项及数据列表的资源窗口,都可以通过它来分类实现。ChildWindow的好处是可以实现拖动及伸缩达到随意布局,更高级的同样可以实现类似最大化、最小化等高级布局功能。
目前Silverlight3.0中自带的ChildWindow感觉仅仅是作为一个富Dialog的范畴应用,我们可以通过在项目中右键->添加->新建项来选择创建一个ChildWindow控件:
然后通过类似如下仅仅几行代码即可激活(弹出)一个300*300的ChildWindow:
QXChildWindow childWindow =new
QXChildWindow() {
Width = 300,
Height = 300,
};
childWindow.Show();
如上图,该ChildWindow将从整个Silverlight应用程序窗口的正中间弹出,并屏蔽掉所有输入事件;此时,如果您突发奇想尝试通过代码连续弹出多个ChildWindow,结果会让您很失望,这些ChildWindow最终只会按顺序一个接一个的出来(即只有关闭掉前一个才会弹出下一个),而无法同时存在于窗口内。
于是,我找到园子里Kinglee写的这篇文章,里面介绍了外国高人Tim
Heuer为我们提供的Non-Modal Used ChildWindow组件(非模式(模态)使用子窗体——Tim
Heuer称之为浮动窗体[FloatableWindow])【下载】【应用程序模板】。大家可以从该文章中的演示Demo体验到此控件的强大~。但是,当我想用它大展拳脚时却发现此控件还是无法实现最大化的界面灵活性。比如它的关闭按钮固定在右上且一直占据着一个位置(带背景且于ZIndex顶部呈现);就算通过设置其Tilte(Object)值等于一张图片,结果仍然会出现Border在整个ChildWindow的外边;外加如果要使用该控件,我们还得引用它的dll(约54k),这对于Silverlight来说似乎大了些。诸多种种的不便迫使我不得不打开源码来看个究竟。
通过对源码的分析,我大致将此控件分成4个关键部分:第一个为顶部用于位移拖动的标题栏;第二个为标题栏右上角的关闭按钮;第三个为中间大面积的内容区域;第四个为右下角的伸缩拖放按钮。
对应的实现原理也很简单,例如拖动标题栏实现ChildWindow的移动是通过对标题栏同时注册鼠标按下、鼠标弹起及鼠标移动事件,并于其中附上相关逻辑来实现;而伸缩拖放则是通过鼠标点击起点及时时的位置之间的逻辑来实现。
按照以上原理,下面我将一步一步为大家演示在Silverlight中如何实现一个简易的可拖动可伸缩的QQ聊天对话面板。
首先创建一个名为QXChildWindow的用户控件,该控件xaml包含着以上描述的4个关键部件Head、Body、CloseButton、Resizer:
<UserControl
x:Class="Silverlight.Control.QXChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
MouseLeftButtonDown="UserControl_MouseLeftButtonDown" Width="555" Height="518">
<Canvas
x:Name="Root">
<!--用于拖动的Title栏-->
<Canvas
x:Name="Head"
Width="553" Height="24"
MouseLeftButtonDown="Head_MouseLeftButtonDown" MouseLeftButtonUp="Head_MouseLeftButtonUp"
MouseMove="Head_MouseMove">
<!--关闭按钮-->
<Image
x:Name="CloseButton"
Width="26" Height="16"
Canvas.Left="514"/>
</Canvas>
<!--主体部分-->
<Canvas
x:Name="Body"
Width="553" Height="494"
Canvas.Top="24">
<!--尺寸伸缩按钮-->
<Image
x:Name="Resizer"
Width="9" Height="9"
Canvas.Left="544" Canvas.Top="484"
MouseLeftButtonDown="Resizer_MouseLeftButtonDown" MouseLeftButtonUp="Resizer_MouseLeftButtonUp"
MouseMove="Resizer_MouseMove" />
</Canvas>
</Canvas>
</UserControl>
头部的拖动功能实现需要Head_MouseLeftButtonDown、Head_MouseLeftButtonUp、和Head_MouseMove这3个事件配合起来实现,即首先通过MouseLeftButtonDown获取鼠标拖动起点位置,且通过CaptureMouse标记鼠标已在Head上处于了按下状态:
privatevoid Head_MouseLeftButtonDown(object
sender,MouseButtonEventArgs e) {
……
Head.CaptureMouse();
isMouseCaptured =true;
clickPoint = e.GetPosition(senderas
UIElement);
}
过程中如果放开了鼠标,我们则取消压下标记并ReleaseMouseCapture:
privatevoid Head_MouseLeftButtonUp(object
sender,MouseButtonEventArgs e) {
Head.ReleaseMouseCapture();
isMouseCaptured =false;
}
如果一直是鼠标按着不动,则我们移动鼠标时将触发拖动整个控件通过TransformGroup进行偏移移动:
privatevoid Head_MouseMove(object
sender,MouseEventArgs e) {
if (isMouseCaptured) {
//假如拖出了窗体范围则return
if (Application.Current !=null
&& Application.Current.RootVisual !=null &&
(e.GetPosition(Application.Current.RootVisual).X < 0 || e.GetPosition(Application.Current.RootVisual).Y
< 0)) {
return;
}
TransformGroup transformGroup =this.RenderTransform
asTransformGroup;
if (transformGroup ==null) {
transformGroup =new
TransformGroup();
transformGroup.Children.Add(this.RenderTransform);
}
TranslateTransform t =new
TranslateTransform() {
X = e.GetPosition(this).X -this.clickPoint.X,
Y = e.GetPosition(this).Y -this.clickPoint.Y
};
if (transformGroup !=null) {
transformGroup.Children.Add(t);
this.RenderTransform = transformGroup;
}
}
}
是不是很简单?其实浮动可拖动自定义窗体是可以如此简单就实现的。这里还有一个极其重要的细节,即该用户控件整体的UserControl_MouseLeftButtonDown事件:
///<summary>
///类静态ZIndex值,通过它可以轻松实现所有QXChildWindow实例被点击后置顶呈现
///</summary>
staticint z;
privatevoid UserControl_MouseLeftButtonDown(object
sender,MouseButtonEventArgs e) {
z++;
Canvas.SetZIndex(this, z);
}
当我们在任意一个QXChildWindow实例上点击左键时,此实例将前置到最前方。仅仅不过使用了一个控件级静态变量z外加如此简单的逻辑即实现了众多弹出的QXChildWindow实例之间的轻松层次管理。
至于整个控件的伸缩,我是通过对所有子控件按比例缩放来实现的;当然,在实际开发中并非一定都按如此,关键要看您的自定义ChildWindow是如何布局与设定的。这部分代码就不罗列了,大家可以自行下载本节的源码进行参考练习。
完全的自定义ChildWindow不仅仅可以实现更灵活的界面布局,而且作为自定义控件的一种,在使用和管理方面都非常的便捷。
教程下载
分享到:
相关推荐
Silverlight 美化ChildWindow效果源 Silverlight 美化ChildWindow效果源
对ChildWindow进行美化,支持最大化最小化窗口.
Silverlight子窗口(ChildWindow)传递参数到父窗口演示
silverlight 美化ChildWindow
1.在子窗口的cpp源文件中(childwindow.cpp),声明一个自定义信号(void mysignal()) 和 一个用于发送自定义信号的自定义槽函数( void sendMysignal() )。 2.在子窗口的cpp源文件中(childwindow.cpp),定义槽函数...
Silverlight的ChildWindow组件给我们的开发带来了便利,比如说我们可以用它开发自定义对话框等。然而,这同时也带来了这样一个问题,ChildWindow组件只能以Modal Window(模式窗口)的形式进行应用,这也就是说同一...
Sliverlight ChildWindow
自定义Silverlight风格的MessageBox,继承自ChildWindow,加入自定义的MessageBoxButton和MessageBoxIcon,现将所有源码和资源分享给大家,希望大家多多指教。另:本程序由C#语言编写,VS2010+Silverlight 4 开发...
<controls:ChildWindow x:Class="Abs.IBR.PI.Project.Examiner" …… xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" …… <controls:ChildWindow.Title> …… ...
silverlight mvvm框架下实现childwindow等窗体应用
MahApps.Metro.SimpleChildWindow, 用于 MahApps.Metro的简单子窗口 MahApps.Metro. SimpleChildWindow 一个用于 MahApps.Metro的简单子窗口。 是,这意味着你需要 MahApps.Metro 来使用这里控件。...
jst simply creating a child window in vp
2.ChildWindow组件(子窗体组件) 3.浮动窗体组件 4.GridSplitter组件 5.TabControl组件 6-7-8.TreeView组件 9.DtarGrid 10.强大的DataGrid组件[2]_数据交互之ADO.NET Entity Framework 11.强大的DataGrid...
otherwise, pop-up windows are the same as overlapped windows of the WS_OVERLAPPE
SilverlightValidator,数据验证,可支持ChildWindow,适用于Silverlight3
var childWindow; function toQzoneLogin() { childWindow =window.open("{dede:global.cfg_phpurl/}/qzonelogin/redirect.php?gourl="+document.URL,"TencentLogin","width=450,height=320,menubar=0,...
使用Extended WPF Toolkit内的ChildWindow窗体控件WPF实现类似MDI子窗体的功能
WS_POPUP 弹出式窗口(不能与WS_CHILDWINDOW样式同时使用) WS_CHILDWINDOW 子窗口(不能与WS_POPUP合用) WS_MINIMIZE 创建窗口拥有最小化按钮 WS_MINIMIZEBOX 创建窗口拥有最小化按钮,须同时指定WS_SYSTEM样式 WS_...