WPF 利用子线程弹出子窗体的研究
一般来说子线程都是用来处理数据的,主窗体用来实现展现,但是有些时候我们希望子窗体实现等待效果,遮挡主窗体并使主窗体逻辑正常进行,这个业务需求虽然不多,但是正好我们用到了,于是我打算把研究成果写在这了。稍后我会上传我的代码,包含测试程序以及之前两边博文谈到的控件,这里我还实现了一个类似雷达扫描的等待窗体,大家可以稍后查看。
实际上这里只有两个难点需要处理,一个就是如何让子窗体遮挡主窗体并位于主窗体中间,另一个就是委托及跨线程访问UI界面。为了方便调用,我在这里写了一个静态的子线程窗体管理类DialogWindowsManager。
1.遮挡主窗体
大家都知道,showDialog方法就是最好的遮挡效果,但是由于它是线程阻塞的,因此每当我们想到这里的时候会有一个误区,认为调用showDialog一定会阻塞前台界面,其实这里的阻塞只是阻塞调用方法所在的线程,并不是一定会阻塞主线程,因此在子线程中调用showDialog方法即可达到效果。实际测试时发现遮挡效果确实有了,可惜每次showDialog的时候窗体会满屏幕乱飞,好吧,最好的方法当然是设置onwer,不过我一直没尝试成功,因为主窗体与子窗体一直处于两个线程中,最后我通过一个算法将位置计算出来之后赋值给了子窗体。代码如下:
/// <summary>
/// 打开等待窗体线程
/// </summary>
public static void ShowWaitingForm(Window onwer) {
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (WaitingFormThread == null)
{
WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
WaitingFormThread.SetApartmentState(ApartmentState.STA);
WaitingFormThread.Start(d);
}
else {
CloseWaitingForm();
ShowWaitingForm(onwer);
}
}
2.跨线程访问
这里不得不说WPF还是很给力的,因为它提供了Dispatcher来获取当前要更新的线程,这里网上资料很多,我就不多做解释了,直接上代码:
/// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setProgrssFormPercent(double d) {
if (cf != null) {
cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
Thread.Sleep();
}
}
3.注意事项
子线程也是UI线程,因此线程一定要设置为ApartmentState.STA状态。
完成的线程管理代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows; namespace MyUserControlLibrary
{
public static class DialogWindowsManager
{
#region 属性 /// <summary>
/// 等待窗体处理线程
/// </summary>
static Thread WaitingFormThread;
/// <summary>
/// 进度条进程
/// </summary>
static Thread CircleProgressFormThread; /// <summary>
/// 等待进度条进程
/// </summary>
static Thread WaitingAndProgressFormThread; /// <summary>
/// 进度条窗体
/// </summary>
static CircleProgressForm cf;
/// <summary>
/// 等待进度条
/// </summary>
static WaitingAndProgressForm wpf;
#endregion #region 私有方法 /// <summary>
/// 打开等待窗体方法
/// </summary>
private static void showWaitingForm(object o)
{
double[] d = (double[])o;
WaitingForm wf = new WaitingForm();
wf.WindowStartupLocation = WindowStartupLocation.Manual;
wf.Top = d[];
wf.Left = d[];
wf.ShowDialog();
} /// <summary>
/// 打开进度条窗体方法
/// </summary>
/// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
private static void showCircleProgressForm(object o)
{
double[] d = (double[])o;
cf = new CircleProgressForm();
cf.WindowStartupLocation = WindowStartupLocation.Manual;
cf.Top = d[];
cf.Left = d[];
cf.ShowDialog();
} /// <summary>
/// 打开进度条窗体方法
/// </summary>
/// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
private static void showWaitingAndProgressForm(object o)
{
object[] m = (object[])o;
double[] d = (double[])m[];
wpf = new WaitingAndProgressForm();
wpf.MainControl.ShowType = (WaitAndProgressType)m[];
wpf.WindowStartupLocation = WindowStartupLocation.Manual;
wpf.Top = d[];
wpf.Left = d[];
wpf.ShowDialog();
} #endregion #region 公有方法 /// <summary>
/// 打开等待窗体线程
/// </summary>
public static void ShowWaitingForm(Window onwer) {
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (WaitingFormThread == null)
{
WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
WaitingFormThread.SetApartmentState(ApartmentState.STA);
WaitingFormThread.Start(d);
}
else {
CloseWaitingForm();
ShowWaitingForm(onwer);
}
} /// <summary>
/// 关闭等待窗体线程
/// </summary>
public static void CloseWaitingForm()
{
WaitingFormThread.Abort();
WaitingFormThread.Join();
WaitingFormThread.DisableComObjectEagerCleanup();
WaitingFormThread = null;
} /// <summary>
/// 打开进度条窗体线程
/// </summary>
public static void ShowCircleProgressForm(Window onwer)
{
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (CircleProgressFormThread == null)
{
CircleProgressFormThread = new Thread(new ParameterizedThreadStart(showCircleProgressForm));
CircleProgressFormThread.SetApartmentState(ApartmentState.STA);
CircleProgressFormThread.Start(d);
Thread.Sleep();
}
else
{
CloseCircleProgressForm();
ShowCircleProgressForm(onwer);
}
} /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setProgrssFormPercent(double d) {
if (cf != null) {
cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
Thread.Sleep();
}
} /// <summary>
/// 关闭进度条窗体线程
/// </summary>
public static void CloseCircleProgressForm()
{
CircleProgressFormThread.Abort();
CircleProgressFormThread.Join();
CircleProgressFormThread.DisableComObjectEagerCleanup();
CircleProgressFormThread = null;
cf = null;
} /// <summary>
/// 打开等待进度条窗体线程
/// </summary>
public static void ShowWaitingAndProgressForm(Window onwer,WaitAndProgressType t)
{
object[] o = new object[];
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
o[] = d;
o[] = t;
if (WaitingAndProgressFormThread == null)
{
WaitingAndProgressFormThread = new Thread(new ParameterizedThreadStart(showWaitingAndProgressForm));
WaitingAndProgressFormThread.SetApartmentState(ApartmentState.STA);
WaitingAndProgressFormThread.Start(o);
Thread.Sleep();
}
else
{
CloseWaitingAndProgressForm();
ShowWaitingAndProgressForm(onwer,t);
}
} /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setWaitingAndProgressFormPercent(double d)
{
if (wpf != null)
{
wpf.Dispatcher.BeginInvoke(new Action(() => { if (wpf != null) { wpf.setPercent(d); } }));
Thread.Sleep();
}
} /// <summary>
/// 关闭等待进度条窗体线程
/// </summary>
public static void CloseWaitingAndProgressForm()
{
WaitingAndProgressFormThread.Abort();
WaitingAndProgressFormThread.Join();
WaitingAndProgressFormThread.DisableComObjectEagerCleanup();
WaitingAndProgressFormThread = null;
wpf = null;
} #endregion
}
}
整个解决方案我会上传的!!
如果喜欢我的文章可以粉我!!!
本文系本人原创,源代码及文章引用转载请注明出处!!谢谢!
源码下载地址:http://files.cnblogs.com/files/lgmbk/UserControlTest.zip
WPF 利用子线程弹出子窗体的研究的更多相关文章
- WPF的WebBrowser屏蔽弹出脚本错误窗体
WPF自带的WebBrowser在訪问一些有问题的网页时常常跳出非常多提示脚本错误的窗体, 可是WPF没有自带屏蔽这些窗体的方法或属性. 所以网上找来一使用反射的方法来屏蔽弹出脚本错误窗体的方法, 非 ...
- WPF 介绍一种在MVVM模式下弹出子窗体的方式
主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...
- WPF 在MVVM模式下弹出子窗体的方式
主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...
- DevExpress第三方控件使用实例之ASPxPopupControl弹出子窗体
弹出页面控件:ASPxPopupControl, <dxpc:ASPxPopupControl ID="popubCtr" runat="server" ...
- WPF:设置弹出子菜单的是否可用状态及效果
需求: 设置弹出子菜单(二级)项仅首项可用,其他项均不可用:不可用是呈灰色效果. 注: 菜单项都是依据层级数据模板.具体格式如下: StackBlock{TextBlock{Image}.TextBl ...
- WPF FileFolderDialog 和弹出子窗口的一些问题
摘要:本文主要是WPF中 FileFolderDialog的相关问题,补充了关于在父窗口弹出子窗口,以及子窗口的相关属性(Data Binding)和命令绑定(Delegate Command)问题, ...
- pyqt5对用qt designer设计的窗体实现弹出子窗口的示例
pyqt5对用qt designer设计的窗体实现弹出子窗口的示例 脚本专栏 python 1. 用qt designer编写主窗体,窗体类型是MainWindow,空白窗口上一个按钮.并转换成mai ...
- 2016 系统设计第一期 (档案一)MVC bootstrap model弹出子页面
通过bootstrap 弹出modal-dialog 子页面 ,例如我要弹出子页面:areaitem_sub_One.html. 具体步骤如下: 第一步:新建 areaitem_sub_One.ht ...
- fancybox 关闭弹出窗口 parent.$.fancybox.close(); 无反应 fancybox 关闭弹出窗口父页面自动刷新,弹出子窗口前后事件
当我们在父页面使用 fancybox 弹出窗口后,如果想自己手动关闭,则可以 function Cancel() { parent.$.fancybox.close(); } 如果关闭没有反应,最好看 ...
随机推荐
- UML--核心元素之参与者Actor
参与者(actor):在系统之外与系统交互的某人或某事物.例如,管理员,用户等等. 参与者位于边界之外,边界之内的都不叫参与者.用一个词来形容更准确,主角.也就是只有主动启动了这个业务的人,才是参与者 ...
- Search in Rotated Sorted Array (I, II) 解答
Question Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 ...
- Linux网络编程--多播
一.多播介绍 什么是多播? 单播用于两个主机之间的端对端通信,广播用于一个主机对整个局域网上所有主机上的数据通信.单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网上的主机进行通信.实际情 ...
- ubuntu下安装Apache+PHP+Mysql(转)
转载自:http://www.comflag.com/2011/05/01/apache-web.htm 步骤一,安装apache2 1 sudo apt-get install apache2 安装 ...
- 2D和3D空间中计算两点之间的距离
自己在做游戏的忘记了Unity帮我们提供计算两点之间的距离,在百度搜索了下. 原来有一个公式自己就写了一个方法O(∩_∩)O~,到僵尸到达某一个点之后就向另一个奔跑过去 /// <summary ...
- QT绘制系统简介
#3个类:QPainter,QPainterDevice 和 QPaintEngine 三个类 #qpainter用于执行绘制操作 #QPainterDevice是一个二维空间抽象,允许qpainte ...
- C库函数笔记
一.string.h 1.memcpy 函数原型:void *memcpy(void *dest, const void *src, size_t n); 功能:从源src所指的内存地址的起始位置开始 ...
- Filter简单介绍
一.简单介绍 Filter也称为过滤器,WEB开发者通过Filter技术.对webserver管理的全部web资源:比如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截.从而实 ...
- hadoop之mapreduse 在Eclipse下的调试环境篇
搭建完毕环境后,開始调试mapreduse程序. 可是遇到不停的报错.本人非常讨厌在自己的操作系统环境变量里设置来设置去,包含linux也是. 通常喜欢把设置环境变量在启动程序的脚本中.让脚本自己执行 ...
- TreeView中右击直接获取节点的方法
在TreeView中无法直接右击得到一个节点,因为当你选中其中一个右击时(不能是第一个)他会默认跳到第一个. 有时我们要想直接右击得到选中的节点,又时我们又想选中直接右击跳出一个快捷菜单怎么办了! 在 ...