WPF界面设计技巧(9)—使用UI自动化布局

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 原文:WPF界面设计技巧(9)—使用UI自动化布局    最近一直没时间更新这系列文章,因为我一直在埋头编写我的第一个WPF应用程序:MailMail   今天开始编写附属的加密/解密工具,对UI自动化布局有些心得,就此分享出来。
原文: WPF界面设计技巧(9)—使用UI自动化布局

 

 

最近一直没时间更新这系列文章,因为我一直在埋头编写我的第一个WPF应用程序:MailMail

 

今天开始编写附属的加密/解密工具,对UI自动化布局有些心得,就此分享出来。

 

我们先来看一下实现的效果:

 

 

 

这样的界面是怎么个自动法呢?请看下图:

 

 

 

就是说界面在适度的伸缩时,不会破坏其布局结构及美观性。

 

这样做有什么好处呢?你可以想象以下情况:

 

1.需要用户或通过程序控制变更窗体尺寸以适应特殊要求时。UI自动化可以伸缩各元素以适应变化后的窗体。

 

2. 软件语言变更,或需要字体/局部元素缩放时。将设计初始时的语言改变为其他语言,按钮、标签等元素呈现所需的最小空间都会有增减,UI自动化可以调整变动元素,并使与之相关的元素也能做出相应的调整。

 

3.需要对UI设计进行更改时。可以说执行UI自动化是一件一劳永逸的事,此后你都不必再为诸如一个标签的文字变更而去调整其他元素的坐标与尺寸了。

 

当然,相比通过窗体设计器“画”界面来说,UI自动化需要更多的知识与经验、更复杂的设计步骤以及更少的可视化编辑器支持,有时可视化的编辑行为甚至会破坏你已有的UI自动化布局,所以要谨慎操作。

 

下面我们就来谈一谈UI自动化所需的各种技巧:

 

让窗口适应内容的大小

 

我们通常所做的都是为Window设置固定的尺寸,然后再向里面填东西,但是也许反过来会更便于操作和使用。

 

清除Window的宽度和高度,并为之设置 SizeToContent="WidthAndHeight" 即可。

 

同理,Window内的布局容器(如Grid)也应当避免使用绝对宽度和高度,除非在其内容无法决定宽度或高度的情况下。

 

但请注意,此类设置可以留在布局即将完成时再进行,否则你可能会在编辑器里看到一个00高的窗体,从而没有了可视化的操作空间。或者,你可以为容器设置较小的MinHeight和MinWidth值,这样它们即保留了伸缩特性,又会具有一定的可视/操作空间。

 

使用Grid进行全局性布局

 

微软把 Grid 作为 Visual Studio 的默认 WPF 模板的布局不是没有道理的,Grid的确可为各种布局控件之首。

 

新接触WPF的朋友可能都对这个复杂的家伙有所退避,比如我开始就每次都把它删掉,换成简单的WrapPanel什么的,可一旦掌握了使用它的方法,那真是爱不释手。

 

Grid 可以说是结合了传统的表格布局与坐标布局的优点的新型布局方案。

 

 

 

 

如你所见,蓝色的线条就是Grid划分的格子,一些元素老老实实的呆在一个格子里,还有一些毫不客气的横跨了多个格子。

 

要设计这样的布局,你需要拿出当年W3C跑出来叫板之前的表格布局网页理念,才能游刃有余地安排元素。

 

元素在格子内的相对位置由其 Margin 操控。

 

其相对的方向采用上、下、左、右均可,但横向和竖向都至少依赖一个方向,通过VerticalAlignment和HorizontalAlignment属性设置。

 

我们来看一下我这个布局的Grid是如何定义的:

 

 

 

 

我定义了3个列,都没有设置宽度,这三列用来承载最下方的三个按钮,我希望按钮的最小尺寸会根据其内容而定,所以不进行绝对值设置。

 

我又定义了5个行,其中4个是具有绝对的高度值,中间的一个就是ListBox所在的区域,我希望界面高度伸缩时,唯一可随之变化的就是这个区域,所以设置为*,但是这时如果我不为Grid指定绝对高度值的话,Grid将无法判断中间这个区域的高度具体应为多少,它把它会变为0,所以我指定了Grid的高度为391

 

让按钮自动化

 

我们可以不为按钮指定固定的宽度或高度,这样它就会随其内容而伸缩了,不过这样按钮边缘会紧贴其内容,这可以通过设置其Padding属性来进行调整:

 

 

 

 

用内容和 Padding 属性撑起了按钮的最小尺寸后,还可以通过 Margin 属性与其所在的 Grid 格子边缘进行关联,这样在格子变小时,不会小于按钮的最小尺寸,格子变大时,按钮会随之伸展。

 

其他元素大都也与按钮同理,如LabelTextBlock

 

利用DockPanel进行局部布局

 

虽然Grid很棒,但我们不能完全依赖于它,满屏幕画上密密麻麻的格子或是一层又一层嵌套的Grid都不便于设计和维护,并且Grid布局会消耗很多的运算资源。

 

对于局部的布局,可以采用更轻量级的布局方案,有时会获得更好的收效,DockPanel就是一种简便的表格布局控件。

 

我通过DockPanel实现了这个区域的布局:

 

 

 

 

这个区域的布局要求是:

 

1.标签居左,采用最小宽度

 

2.按钮居右,采用最小宽度

 

3.中间的空档由密码框完全占据

 

实现的代码是这样:

 

 

 

 

通过DockPanel.Dock属性可以设置元素位于DockPanel布局方位。

 

标签未设置该属性,因为其默认为居左,也就是DockPanel.Dock="Left"。

 

按钮设置为 DockPanel.Dock="Right"

 

本该排列在第二,也就是会居中并填满空白区域的密码框写在了最后,并且也未设置DockPanel.Dock属性,难道它也是采用了默认的 DockPanel.Dock="Left" 吗?非也,如果你显式设置为DockPanel.Dock="Left",它就会向左排在标签后面,并缩成一小团,非常难看。这其实是因为DockPanel有一个默认为真的属性:

 

 

 

 

最后一个元素会用以填满剩余的区域。

 

这个设计手法看起来是不是很像CSS布局时设置的Float浮动属性?

 

 

好了,就分享到这里了,代码奉上:

 

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif Code
<Window x:Class="MailMailPassBox.Window1"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    Style
="{StaticResource subWindow}"
    MouseLeftButtonDown
="Window_MouseLeftButtonDown"
    Loaded
="Window_Loaded"
        DragEnter
="Window_DragEnter"
        Drop
="Window_Drop"
    Title
="Window1" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" ShowInTaskbar="True" AllowDrop="True">
    
<Grid Height="391">
        
<Grid.ColumnDefinitions>
            
<ColumnDefinition/>
            
<ColumnDefinition/>
            
<ColumnDefinition/>
        
</Grid.ColumnDefinitions>
        
<Grid.RowDefinitions>
            
<RowDefinition Height="15" />
            
<RowDefinition Height="60" />
            
<RowDefinition Height="*" />
            
<RowDefinition Height="28" />
            
<RowDefinition Height="42" />
        
</Grid.RowDefinitions>
        
<Border Background="#989898" BorderBrush="#989898" BorderThickness="2,0,2,2"  Margin="0,0,5.643,0"  Height="14.75" VerticalAlignment="Top" Grid.ColumnSpan="3" HorizontalAlignment="Right" Width="111">
            
<WrapPanel>
            
<CheckBox ToolTip="{StaticResource 窗口总在最前提示}" Height="12.75" Name="top" Click="top_Click" Background="{StaticResource top}" Width="35" Content="Close" Margin="0,0,1,0" HorizontalAlignment="Stretch" VerticalAlignment="Top" Template="{StaticResource barCheckBox}"/>
            
<Button Height="12.75" Name="mini"  ToolTip="{StaticResource 最小化提示}"  Click="mini_Click" Background="{StaticResource mini}" Width="35" Content="Close" Margin="0,0,1,0" HorizontalAlignment="Stretch" VerticalAlignment="Top" Template="{StaticResource barButton}"/>
            
<Button Height="12.75" Name="close" ToolTip="{StaticResource 关闭提示}" Click="close_Click" Background="{StaticResource close}" Width="35" Content="Close" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Top" Template="{StaticResource barButton}"/>
            
</WrapPanel>
        
</Border>
        
<Rectangle Fill="{StaticResource title2}" Margin="7,0" Name="rectangle1" Stroke="Black" Grid.Row="1" StrokeThickness="0" Grid.ColumnSpan="3" />
        
<GroupBox Grid.Row="2" Margin="7" Name="groupBox1" Grid.ColumnSpan="3">
            
<GroupBox.Header>
                
<WrapPanel>
                    
<TextBlock>待加密/解密文件 (</TextBlock>
                    
<TextBlock Text="{Binding ElementName=listBox1, Path=Items.Count}"/>
                    
<TextBlock>)</TextBlock>
                
</WrapPanel>
            
</GroupBox.Header>
            
<ListBox PreviewMouseRightButtonDown="listBox1_PreviewMouseRightButtonDown" MouseDoubleClick="listBox1_MouseDoubleClick" ToolTip="{StaticResource 文件列表提示}" Name="listBox1" SelectionMode="Multiple">
                
<ListBox.ContextMenu>
                    
<ContextMenu>
                        
<MenuItem Name="cmi2" Header="删除所有选中的文件" Click="cmi2_Click"/>
                        
<MenuItem Name="cmi3" Header="清空文件列表" Click="cmi3_Click"/>
                    
</ContextMenu>
                
</ListBox.ContextMenu>
            
</ListBox>
        
</GroupBox>
        
<DockPanel Grid.Row="3" Margin="0" Name="dockPanel1" Grid.ColumnSpan="3">
            
<Label Height="28" Name="label1" Margin="7,0,0,0">密钥:</Label>
            
<Button Height="23" Name="button4" DockPanel.Dock="Right" Padding="8,3" Margin="7,0">粘帖入</Button>
            
<PasswordBox Height="23" Name="passwordBox1"/>
        
</DockPanel>
        
<Button Grid.Row="4" Margin="7" Name="button1" Padding="8,3" MinWidth="64">直接加密/解密</Button>
        
<Button Grid.Column="1" Grid.Row="4" Margin="0,7" Name="button2" Padding="8,3" MinWidth="64">加密/解密并备份原文件</Button>
        
<Button Grid.Column="2" Grid.Row="4" Margin="7" Name="button3" Padding="8,3" MinWidth="64">加密/解密到指定目录..</Button>
    
</Grid>
</Window>

 

当然,你不能期待直接编译或使用这个代码了,它只是我的程序的一部分。

 

我会在以后更多地分享我在编写 MailMail 期间获得的经验的,现在的任务是赶紧把它造出来,嘿嘿。

 

现在是这个样子滴:

 

 

更多抓图还是看我这个帖子了:一起来乐邮邮——妙趣小软件:MailMail发布预告

 

目录
相关文章
|
3天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
20 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
29天前
|
Android开发 开发者 容器
flutter:&UI布局 (六)
本文档介绍了Flutter中的UI布局方式,包括线性布局(如Column和Row)、非线性布局(如Stack、Flex、Positioned)以及Wrap布局等。通过具体示例代码展示了如何使用这些布局组件来构建灵活多变的用户界面,例如使用Column垂直排列文本、使用Stack叠加组件、以及利用Wrap实现自动换行的按钮布局等。
|
2月前
|
搜索推荐 前端开发 C#
推荐7款美观且功能强大的WPF UI库
推荐7款美观且功能强大的WPF UI库
|
3月前
|
持续交付 jenkins Devops
WPF与DevOps的完美邂逅:从Jenkins配置到自动化部署,全流程解析持续集成与持续交付的最佳实践
【8月更文挑战第31天】WPF与DevOps的结合开启了软件生命周期管理的新篇章。通过Jenkins等CI/CD工具,实现从代码提交到自动构建、测试及部署的全流程自动化。本文详细介绍了如何配置Jenkins来管理WPF项目的构建任务,确保每次代码提交都能触发自动化流程,提升开发效率和代码质量。这一方法不仅简化了开发流程,还加强了团队协作,是WPF开发者拥抱DevOps文化的理想指南。
80 1
|
3月前
|
持续交付 jenkins C#
“WPF与DevOps深度融合:从Jenkins配置到自动化部署全流程解析,助你实现持续集成与持续交付的无缝衔接”
【8月更文挑战第31天】本文详细介绍如何在Windows Presentation Foundation(WPF)项目中应用DevOps实践,实现自动化部署与持续集成。通过具体代码示例和步骤指导,介绍选择Jenkins作为CI/CD工具,结合Git进行源码管理,配置构建任务、触发器、环境、构建步骤、测试及部署等环节,显著提升开发效率和代码质量。
73 0
|
3月前
|
C# 开发者 Windows
全面指南:WPF无障碍设计从入门到精通——让每一个用户都能无障碍地享受你的应用,从自动化属性到焦点导航的最佳实践
【8月更文挑战第31天】为了确保Windows Presentation Foundation (WPF) 应用程序对所有用户都具备无障碍性,开发者需关注无障碍设计原则。这不仅是法律要求,更是社会责任,旨在让技术更人性化,惠及包括视障、听障及行动受限等用户群体。
79 0
|
3月前
|
持续交付 C# 敏捷开发
“敏捷之道:揭秘WPF项目中的快速迭代与持续交付——从需求管理到自动化测试,打造高效开发流程的全方位指南”
【8月更文挑战第31天】敏捷开发是一种注重快速迭代和持续交付的软件开发方法,通过短周期开发提高产品质量并快速响应变化。本文通过问题解答形式,探讨在Windows Presentation Foundation(WPF)项目中应用敏捷开发的最佳实践,涵盖需求管理、版本控制、自动化测试及持续集成等方面,并通过具体示例代码展示其实施过程,帮助团队提升代码质量和开发效率。
70 0
|
3月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
64 0
|
3月前
|
开发者 C# UED
WPF与多媒体:解锁音频视频播放新姿势——从界面设计到代码实践,全方位教你如何在WPF应用中集成流畅的多媒体功能
【8月更文挑战第31天】本文以随笔形式介绍了如何在WPF应用中集成音频和视频播放功能。通过使用MediaElement控件,开发者能轻松创建多媒体应用程序。文章详细展示了从创建WPF项目到设计UI及实现媒体控制逻辑的过程,并提供了完整的示例代码。此外,还介绍了如何添加进度条等额外功能以增强用户体验。希望本文能为WPF开发者提供实用的技术指导与灵感。
136 0
|
3月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
55 0

热门文章

最新文章

下一篇
无影云桌面