WPF 进阶 窗口
45-50 2.3h
Window类
显示窗口
ShowDialog()方法显示模态窗口。模态窗口通过锁住所有鼠标和键盘输入来阻止用户访问
父窗口,直到模态窗凵被关闭。此外,直到模态窗口被关闭后,ShowDialog()方法才返回。所
以,在ShowDiag()方法调用之后放置的任何代码都会被阻塞(然而,这并不意味着其他代码无
法运行。例如,如果有正在运行的计时器,那么计时器的事件处理程序仍将运行)·在代码中,
通常的模式是显示一个模态窗口,等待直到它被关闭,然后使用它的数据。
Show()方法显示非模态窗口,非模态窗口不会阻止用户访问其他任何窗口。而且当窗口显
示之后,Show()方法会立即返回,以后续代码语句会立即执行。可创建并显示几个非模态窗
口,而且用户能够同时和它们进行互。当使用非模态窗口时,有时需要同步代码,以确保在
一个窗口中的改变能更新另一个窗凵中的信息,从血防止用户使用无效的信息。
定位窗口
SystemParameters类包含大量静态属性,可返回各种有关系统设置的信息。例如,可使用
SystemParameters类决定用户是否启用了热跟踪选项、拖动整个窗口选项以及其他
选项。对于窗口,systemParameters类特别有用,因为它提供的两个属性可给出当前屏幕的大
刁、:FullPrimaryScreenHeight和FullPnmaryScreenWidth。这两个属性都非常简单,下面是一些(在
运行时将窗口定位在屏幕中央)演示代码:
double screenHeight=Systempararmeters.FullPrimaryScreenHeight double screenWidth=Systempararmeters.FullPrimaryScreenWidth this.Top=(ScreenHeight - this.Height)/2 this.Left=(screenWidth-this.Width)/2
更好的选择是使用SystemParameters.WorkArea矩形,使窗凵位于可用屏幕区域的中央。工
作区域不包括停靠任务栏(以及其他停靠到桌面的工具栏)的区域。
保存和还原窗口的位置
经常需要让窗口记住它上一次的位置。这一信息可存储到特定于用户的配置文件或
Windows注册表中。
如果希望在特定于用户的配置文件中存储重要窗口的位置,可首先双击SolutionExporer
中的Properhes节点,然后选择Settings选项卡。接着使用system.WindowsRect数据类型添加
用户范围的设置
namespace Windows { public class WindowPositionHelper { public static string RegPath = @"Software\MyApp\"; public static void SaveSize(Window win) { // Create or retrieve a reference to a key where the settings // will be stored. RegistryKey key; key = Registry.CurrentUser.CreateSubKey(RegPath + win.Name); key.SetValue("Bounds", win.RestoreBounds.ToString(System.Globalization.CultureInfo.InvariantCulture)); } public static void SetSize(Window win) { RegistryKey key; key = Registry.CurrentUser.OpenSubKey(RegPath + win.Name); if (key != null) { Rect bounds = Rect.Parse(key.GetValue("Bounds").ToString()); win.Top = bounds.Top; win.Left = bounds.Left; // Only restore the size for a manually sized // window. if (win.SizeToContent == SizeToContent.Manual) { win.Width = bounds.Width; win.Height = bounds.Height; } } } } public class WindowPositionHelperConfig { public static void SaveSize(Window win) { Properties.Settings.Default.WindowPosition = win.RestoreBounds; Properties.Settings.Default.Save(); } public static void SetSize(Window win) { Rect rect = Properties.Settings.Default.WindowPosition; win.Top = rect.Top; win.Left = rect.Left; // Only restore the size for a manually sized // window. if (win.SizeToContent == SizeToContent.Manual) { win.Width = rect.Width; win.Height = rect.Height; } } } }
窗口交互
窗口所有权
.NET允许一个窗口“拥有”其他窗口。对于浮动的工具框和命令窗口而言,被拥有的窗口
是很有用的。被拥有的窗口的典型示例是Microsoftword中的查找和替换窗口。当所有者窗口
最小化时,也会自动最小化被拥有的窗口当被拥有的窗口与拥有者窗口相互重叠时,被拥有
的窗口总显示在上面。
为支持窗口之间的拥有关系,Window类增加了两个属性。Owner属性是指向窗口的引用,
引用的窗口拥有当前窗口(如果存在的话)。OwnedWindows属性是当前窗口拥有的所有窗口
(如果包含有窗凵的话)的集合。
被拥有的窗口始终以非模态方式显示。为移除被拥有的窗口,需要将其Owner属性设置为
空引用。
设置拥有关系就是简单地设置Owner属性,如下所示:
ToolWindow wintool =new ToolWindow(); winTool.Owner=this; winTool.Show();
对话框模型:
通常,当显示模态窗口时是为了给用户提供一些选择。显示窗口的代码等待选择结果,
然后根据选择执行相应的操作。这种设计称为对话框模型@alogmodel)。以模态方式显示的窗
口就是对话框。
幸运的是,这种结构的某些内容己经被固化到Window类中。每个窗口都包含预先准备好
的DialogResult属性,该属性可以设置为e、false或null值。通常,true表示用户选择继续
进行操作(例如,单击OK按钮),而f;小e表示用户取消了操作。
最方便的是,一旦设置DialogResult属性,就会为调用代码返回该属性值作为ShowDialog()
方法的返回值。
DialogWindow dialog=new DialogWindow(): if(dialog.ShowDialog()==true) { }else { }
通用对话框:
Windows操作系统提供了许多内置对话框,可通过WindowsAPI访问这些对话框。WPF
为其中的几个对话框提供了封装程序。
最常见的对话框是System.Windows.MessageBox类,该类提供了静态的Show()方法。可使
用该类显示标准的Windows消息框。
除MessageBox类外,WPF还提供了支持专门用于打印的PrintDialog类,
以及在Microsoft.Win32名称空间中定义的OpenFileDialog和SaveFileDialog类。
OpenFileDialog和SaveFileDialog类需要一些额外特性(其中一些特性继承自Fi1eDialog类)。
这两个类都支持过滤字符串,用于设置允许的文件扩展名。OpenFileDialog类还提供了其他属
性,包括用于检查用户选择的属性(CheckFileExists),以及允许选择多个文件的属性(MuItiseIect)。
下面是一个示例,该例显示一个OpenFileDialog对话框,并且当对话框关闭后在列表框中显示
用户选择的文件:
private void cmdOpen_Click(object sender, RoutedEventArgs e) { OpenFileDialog myDialog = new OpenFileDialog(); myDialog.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF" + "|All files (*.*)|*.*"; myDialog.CheckFileExists = true; myDialog.Multiselect = true; if (myDialog.ShowDialog() == true) { lstFiles.Items.Clear(); foreach (string file in myDialog.FileNames) { lstFiles.Items.Add(file); } } }
非矩形窗口:
简单形状窗口:
创建简单形状窗口需要使用以下几个步骤:
(I)将WindowAllowsTransparency属性设置为trueo
(2)将Window.WindowStyle属性设置为None,从而隐藏窗口的非客户区(蓝色边框)。如果
不这样做,当试图显示窗口时会抛出InvalidOperationException异常。
(3)将窗口背景设置为透明(可使用Transparent颜色,该颜色的alpha值为0),或将背景设
置为具有透明区域的图像(透明区域是使用alpha值为0的颜色绘制的区域)。
这三个步骤可有效地移除窗口的标准外观(对于WPF专业人员来说,这些标准外观就是窗
口的装饰元素)。
为得到简单形状窗口效果,现在需要提供一些不透明的具有所需形状的内容。
有多种选择:
使用支持透明格式的文件提供背景插图。例如,可使用PNG文件提供窗凵的背景。这是
比较简明直观的方法,并且如果正在和未掌握XAML知识的设计人员合作,这种方法是
比较合适的。然而,因为在具有更高系统DPI的窗凵中呈现时需要使用更多的像素,背
景图形可能会变得模糊。当允许用户改变窗口尺寸时,也存在这一问题。
使用WPF中的形状绘制功能创建具有矢量内容的背景。不管是改变窗口尺寸还是改变系
统DPI设置,该方法可以确保不损失质量。然而,可能希望使用支持XAML的设计工具,
例如ExpressionBIend0
更简单的具有所需形状的WPF元素。例如,可使用Border元素创建出具有圆角边缘
的美观窗口。通过这一方法不需要额外的设计工作,就可以实现具有现代Office风格的
窗口外观。
透明窗口的骨架:
<Window x:Class="Windows.TransparentBackground" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Windows" Height="300" Width="300" WindowStyle="None" AllowsTransparency="true" MouseLeftButtonDown="window_MouseLeftButtonDown" > <Window.Background> <ImageBrush ImageSource="shapes.png"></ImageBrush> </Window.Background> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Button Margin="20">A Sample Button</Button> <Button Margin="20" Grid.Row="2" Click="cmdClose_Click">Close</Button> </Grid> </Window>
具有形状内容到透明窗口:
移动形状窗口:
改变形状窗口的尺寸:
组合到一起:窗口到自定义空间模板: