UWP开发入门(五)——自定义Panel
各位好,终于讲到自定义Panel了。当系统自带的几个Panel比如Gird,StackPanel,RelativePanel不能满足我们的特定要求时(其实不常见啦),自定义Panel就显得非常必要,而且因为是针对性的处理,效果也会非常好。更何况自定义Panel其实并不复杂,今天俺们就来学习一下。
记得上一篇自定义CommandBar在增加占位控件AppBarEmpty时,采用的是通过Page的SizeChanged事件中计算页面Width,减去CommandBar中其他控件Width后再赋值Width给AppBarEmpty的方法。就可行性而言是绝对没问题的,代码复杂度也很低,不失为一个好方法。但是复用性不太好,需要在每个Page都写上一小段代码。而我们的初衷是希望AppBarEmpty能够自动撑开,计算自身所需的Width。
遇到的困难来自StackPanel这个控件,StackPanel在计算自身所需空间时,会非常吝啬按children元素所需的最小尺寸来申请。就好比申请经费时按最下限申请,这种精神ZF部门应该学习,而公司组织TeamBuilding就应该排斥……)。说到这里,本篇的主题有了,就是通过自定义一个StackPanelEx来实现让AppBarEmpty自动撑开的效果。
前面说了,自定义Panel其实并不复杂。只有两个方法需要override:
//
// Summary:(根据子元素测量控件本身需要的空间)
// Provides the behavior for the Measure pass of the layout cycle. Classes can override
// this method to define their own Measure pass behavior.
//
// Parameters:
// availableSize:(控件本身的可用空间。如指定无穷大值,表示控件的大小将调整为内容的可用大小)
// The available size that this object can give to child objects. Infinity can be
// specified as a value to indicate that the object will size to whatever content
// is available.
//
// Returns:(控件根据子元素大小计算得出的所需大小)
// The size that this object determines it needs during layout, based on its calculations
// of the allocated sizes for child objects or based on other considerations such
// as a fixed container size.
protected virtual Size MeasureOverride(Size availableSize);
//
// Summary:(根据上面测量的结果,来对子元素进行布局)
// Provides the behavior for the Arrange pass of layout. Classes can override this
// method to define their own Arrange pass behavior.
//
// Parameters:
// finalSize:(控件用来排列自身及其子元素的最终确定的空间)
// The final area within the parent that this object should use to arrange itself
// and its children.
//
// Returns:(使用的实际大小)
// The actual size that is used after the element is arranged in layout.
protected virtual Size ArrangeOverride(Size finalSize);
听上去是不是挺绕的?我们来看StackPanelEx的实际代码:
public class StackPanelEx : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
double height = ;
foreach (var child in Children)
{
// Tell the child control to determine the size needed
child.Measure(availableSize);
height = child.DesiredSize.Height > height ? child.DesiredSize.Height : height;
} return new Size(availableSize.Width,height);
} protected override Size ArrangeOverride(Size finalSize)
{
int count = Children.Count(_ => _ is AppBarEmpty2);
double totalLength = Children.Where(_ => _ is AppBarEmpty2 == false).Sum(_ => (_ as FrameworkElement).Width);
var emptyWidth = (finalSize.Width - totalLength) / count; double x = ;
foreach (var child in Children)
{
if (child is AppBarEmpty2)
{
child.Arrange(new Rect(x, , emptyWidth, ));
x += emptyWidth;
}
else
{
child.Arrange(new Rect(x, , child.DesiredSize.Width, child.DesiredSize.Height));
x += child.DesiredSize.Width;
}
}
return finalSize;
}
}
简单解释一下,首先在MeasureOverride方法里,告诉每个子元素(这里是AppBarButton和AppBarEmpty2)去算自己需要多少空间,一会要分地了。然后直接告诉上头,Width我全要了,Height按我们村里最高的人给就行了。
紧接着到了ArrangeOverride方法,上级领导比较大方,告诉该控件Width全给你,还有你Height要的太少,拖了上级Panel的后腿,多给一些Height免得挤到同级的其他控件……
然后村长及开始分地了。AppBarButton就按他自己申请的给,AppBarEmpty2感觉是村长亲戚,剩下的Width全给他们家承包了……
最后向上头汇报一下分地的情况,这事就算完了。
AppBarEmpty2还是没变,和上次一样。
public class AppBarEmpty2 : FrameworkElement, ICommandBarElement
{
public bool IsCompact { get; set; }
}
既然新的StackPanelEx写好了,就该替换CommandBar原有的StackPanel了,找到CommandBar模板中关于PrimaryItemsControl的部分
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentControl x:Name="ContentControl" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="False" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ItemsControl x:Name="PrimaryItemsControl" Grid.Column="0"
HorizontalAlignment="Stretch" IsTabStop="False" MinHeight="{ThemeResource AppBarThemeMinHeight}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!--<StackPanel Orientation="Horizontal"/>-->
<local:StackPanelEx ></local:StackPanelEx>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
将ItemsPanelTemplate中的StackPanel替换成StackPanelEx,同时将ItemsControl的HorizontalAlignment="Right"改成HorizontalAlignment="Stretch",大功告成,再来看一下Page中的XAML部分:
<CommandBar x:Name="commandBar" Grid.Row="3" Style="{StaticResource CommandBarStyle2}" >
<AppBarButton x:Name="appbarButton" Icon="Accept" Label="fdsfdsf" ></AppBarButton>
<local:AppBarEmpty2 ></local:AppBarEmpty2>
<AppBarButton Icon="Accept" Label="fdsfdsf"></AppBarButton>
<local:AppBarEmpty2 ></local:AppBarEmpty2>
<AppBarButton Icon="Accept" Label="fdsfdsf" ></AppBarButton>
</CommandBar>
是不是非常的清爽,再也不用去写什么SizeChanged事件了。实际效果如下图:
UWP开发入门(五)——自定义Panel的更多相关文章
- UWP开发入门(四)——自定义CommandBar
各位好,再次回到UWP开发入门系列,刚回归可能有些不适应,所以今天我们讲个简单的,自定义CommandBar,说通俗点就是自定义类似AppBarButton的东西,然后扔到CommandBar中使用. ...
- openresty 前端开发入门五之Mysql篇
openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...
- UWP开发入门(十六)——常见的内存泄漏的原因
本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...
- UWP开发入门系列笔记之(一):UWP初览
标签: 随着微软Build2015带来的好消息,Win10正式版发布的日子已经离我们越来越近了,我们也终于欣喜地看到:一个统一的Windows平台对于开发人员来说充满了吸引力,这局棋下的好大的说--于 ...
- UWP开发入门(十)——通过继承来扩展ListView
本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念.而是通过继承的方法来扩展一个现有的类,在继承的 ...
- UWP开发入门(25)——通过Radio控制Bluetooth, WiFi
回顾写了许久的UWP开发入门,竟然没有讲过通过Windows.Devices.Radios.Radio来控制Bluetooth和WiFi等功能的开关.也许是因为相关的API设计的简单好用,以至于被我给 ...
- UWP开发入门(十一)——Attached Property的简单应用
UWP中的Attached Property即附加属性,在实际开发中是很常见的,比如Grid.Row: <Grid Background="{ThemeResource Applica ...
- UWP开发入门(七)——下拉刷新
本篇意在给这几天Win10 Mobile负面新闻不断的某软洗地,想要证明实现一个简单的下拉刷新并不困难.UWP开发更大的困难在于懒惰,缺乏学习的意愿.而不是“某软连下拉刷新控件都没有”这样的想法. 之 ...
- UWP开发入门(一)——SplitView
接下来会写一个UWP(Universal Windows Platform)开发入门的系列,自己学习到哪里,有什么心得总结,就会写到哪里.本篇对适用于顶层导航的SplitView控件展开讨论. 首先S ...
随机推荐
- uva-10879-因数分解
把一个数分解成n*m的形式,一定存在 解题思路: 一个大于1的正整数最小因数一定是素数 ac时间80ms,感觉慢了,可惜看不到0ms的大神代码 #include <iostream> #i ...
- tesseract-ocr训练方法
tesseract-ocr有2和3两个版本,不同版本训练方法稍有不同. 第3版本的训练方法官版教程在这里:TrainingTesseract3 第2版的训练方法官版教程在这里:TrainingTess ...
- j2ee常用jar包
[b]activation.jar:[/b]与javaMail有关的jar包,使用javaMail时应与mail.jar一起加入到lib中去,具体负责mail的数据源和类型等 [b]ajaxtags- ...
- 用JDK自带的包来解析XML文件(DOM+xpath)
DOM编程不要其它的依赖包,因为JDK里自带的JDK里含有的上面提到的org.w3c.dom.org.xml.sax 和javax.xml.parsers包就可以满意条件了.(1)org.w3c.do ...
- notepad++ 行首行尾添加字符
有一次要处理SQL,拿到了脚本.但是要将其写入java 代码中,要在行首和行尾添加上引号.利用notepad++进行编辑. $表示行尾,^表示行首. 如上图,就这样.很高效. 如果只是在行尾添加字符, ...
- 模板引擎 引自 《PHP核心技术与最佳实践》
随着web的发展,仅一门语言或者一种技术已经不能满足需求,分层架构显得越来越重要.在大型架构中,从来不会简单地应用php从头到尾实现一个完整的mvc架构.可能底层是c/java的支撑,负责密集运算和y ...
- oracle 导入导出指定表
导出 exp username/password@127.0.0.1/orcl file=D:\xxx.dmp tables(tablename,tablename) 导入 imp username/ ...
- 什么是First-class citizen?
[什么是First-class citizen?] In programming language design, a first-class citizen (also type, object, ...
- 和大于S的最小子数组 · Minimum Size Subarray Sum
[抄题]: 给定一个由 n 个正整数组成的数组和一个正整数 s ,请找出该数组中满足其和 ≥ s 的最小长度子数组.如果无解,则返回 -1. 给定数组 [2,3,1,2,4,3] 和 s = 7, 子 ...
- python全栈考试
1.执行 Python 脚本的两种方式 shell直接调用python脚本 python run.py 调用解释器来调用脚本 2.2.简述位.字节的关系 每8个位bit,组成一个字节byte. 一个 ...