WPF中的 Layout To Layout

简介: 原文:WPF中的 Layout To Layout                     WPF中的 Layout To Layout                            周银辉 WPF的布局功能异常强大,当有时我们会有一些奇怪的需求:布局之间的切换。
原文: WPF中的 Layout To Layout

                     WPF中的 Layout To Layout
                            周银辉

WPF的布局功能异常强大,当有时我们会有一些奇怪的需求:布局之间的切换。比如动态地将控件在UniformGrid布局和StackPanel布局之间切换。这种需求是有意义的,比如Blend中的DesignWorkspace和AnimationWorkspace切换功能。WPF可以轻松做到这一点。

1, 无过渡动画的直接切换:
这没有什么讨论的必要了,要将控件从源布局切换到目标布局,只需要简单地将该控件从源布局控件中删除然后添加到目标布局控件中就可以了。

2, 有过度动画的切换:

这才是我们这篇文章要讨论的。为了明白我在说什么,你可以先下载这个程序运行一下以观察该类型的切换。

基本原理

假设有几个Button控件要在UniformGrid布局和StackPanel布局之间切换,我们可以这样来实现:

就其中的一个按钮btn1而言,无论btn1被加载到哪个面板中,都是先从上一个面板中将btn1删除,然后在调用另外一个面板的Children.Add方法,该动作都是瞬间完成的,除非修改面板内部逻辑,不可以产生动画,更不可能有过度效果.

那么事实上,我们既不将btn1放到UnifromGrid中也不把它放到StackPanel中,而是将它放到一个Canvas中.并且Canvas与UnifromGrid以及StackPanel重合. 而放到UnifromGrid或StackPanel中的是另外一个元素:我们称为LayoutToLayoutTarget(Target),切换布局的时候,事实上,我们是将Target从一个面板中删除然后在加到另一个面板中,与此同时,我们的btn1参照Target在新面板中的位置和大小来作为其动画的目标值,然后利用动画来到变化到此值.当由于其他原因(比如用户改变窗口大小等)导致Target位置或大小发生变化时,我们的btn1也会立即做出相应的变化(而不采用动画来渐变了).可以看出btn1始终在Canvas中,只是大小和位置发生了变化,而让人产生了错觉

这里的btn1只是一个特例,为了让所有的控件都可以达到这个效果而不仅仅是Button,我们就使用LayoutToLayoutHost来包含其他控件(host.Child=myBtn).Host的行为为上面的btn1完全一样.

public class LayoutToLayoutTarget : Border

LayoutToLayoutTarget用来指示LayoutToLayoutHost的大小以及将放置在什么位置.当布局变化时,先将LayoutToLayoutTarget变化到合适的位置和大小, 然后LayoutToLayoutHost再根据LayoutToLayoutTarget的大小和位置来进行动画

public class LayoutToLayoutHost : Border

LayoutToLayoutHost用来Host控件. LayoutToLayoutTarget用来指示LayoutToLayoutHost的大小以及将放置在什么位置.当布局变化时,先将LayoutToLayoutTarget变化到合适的位置和大小, 然后LayoutToLayoutHost再根据LayoutToLayoutTarget的大小和位置来进行动画

使用前的准备工作是:

                //初始化一个LayoutToLayoutTarget

                LayoutToLayoutTarget target = new LayoutToLayoutTarget();

                //设置目标大小

                target.MinWidth = 80;

                target.MinHeight = 50;

                this.targets.Add(target);

                //将其放置在源布局控件中

                this.uniformGrid1.Children.Add(target);

                

               //初始化一个LayoutToLayoutTarget

                LayoutToLayoutHost host = new LayoutToLayoutHost();

                //先将host放在Canvas中

this.canvas1.Children.Add(host);

               //demoButton为我们要改变布局的控件

                Button demoButton = new Button();

                demoButton.Content = "# " + i;

                //将它放在host中

host.Child = demoButton;

                //将host和target联系起来

                host.BindToTarget(target);

改变布局时:

               //将target从源布局控件中删除

               this.uniformGrid1.Children.Remove(target)

                //将target添加到目标布局控件中

this.stackPanel1.Children.Add(target);

//开始动画

host.BeginAnimating(false);

如果觉得一头雾水的话,可以在这里下载DEMO谢谢

目录
相关文章
|
C# Windows
WPF Layout 系统概述——Measure
原文:WPF Layout 系统概述——Measure 前言 在WPF/Silverlight当中,如果已经存在的Element无法满足你特殊的需求,你可能想自定义Element,那么就有可能会面临重写MeasureOverride和ArrangeOverride两个方法,而这两个方法是WPF/SL的Layout系统提供给用户的自定义接口,因此,理解Layout系统的工作机制,对自定义Element是非常有必要的。
1035 0
|
C#
WPF笔记(2.3 StackPanel)——Layout
原文:WPF笔记(2.3 StackPanel)——Layout StackPanel用于小规模的排版布局,比如说一个局部下几个textbox和Button啦。Orientation属性有Vertical和Horizontal两种选择,决定布局方向。
725 0
|
C#
WPF笔记(2.2 DockPanel)——Layout
原文:WPF笔记(2.2 DockPanel)——Layout读完了这一节,发现DockPanel就是过去winform中的Dock属性。原来的Dock属性是子控件设置,而其父亲级别不用设置。现在WPF改为在父亲级别抽象出一个DockPanel,然后设置其下子控件的Dock属性。
1044 0
|
容器 C#
WPF笔记(2.4 Grid)——Layout
原文:WPF笔记(2.4 Grid)——Layout 第一章已经简单介绍过这个容器,这一节详细介绍。Grid一般是用表格(Grid.Row 和Grid.Column )的,比StackPanel更细致一些,但是,这么玩很麻烦,先横着竖着定义一大堆,然后把元素指定其表格位置,即插入数据,和我们平常习惯的HTML表格不太一样,甚至更麻烦了。
892 0
|
前端开发 C#
WPF笔记(2.6 ViewBox)——Layout
原文:WPF笔记(2.6 ViewBox)——Layout 在Canvas外面包一层ViewBox,可以使Canvas内的控件填充整个ViewBox,并随着ViewBox的大小变化而同步变化,这是因为ViewBox默认属性Stretch=“Uniform”。
1269 0
|
前端开发 容器 C#
WPF笔记(2.5 Canvas)——Layout
原文:WPF笔记(2.5 Canvas)——Layout Canvas是最精确的布局容器——绝对定位,此书作者不建议使用,以为控件的大小一般会随着内部字体图片的动态生成而自动变化,所以使用前三种布局是最好的选择,在这一点上,我也持同样意见。
813 0
|
XML 数据格式 容器
WPF笔记(2.7 文字布局)——Layout
原文:WPF笔记(2.7 文字布局)——Layout 这一节介绍的是文字布局的几个控件:1.TextBlock      最基本的文字控件可以配置5个Font属性。TextWraping属性,"Wrap"是换行,NoWrap是不换行(原书有误,在此更正)。
960 0
|
容器 C#
WPF笔记(2.9和2.10)——Layout
原文:WPF笔记(2.9和2.10)——Layout  2.9讲的是,如果内部设定超过容器大小,怎么办?StackPanel会裁剪越界部分DockPanel和Grid会智能判断,从而决定换行。 2.10 自定义布局容器自定义容器要实现两个方法MeasureOverride和ArrangeOverride,并保证遍历其下的所有子控件,使他们都执行Measure和Arrange方法。
903 0
|
C#
WPF笔记(2.8 常用的布局属性)——Layout
原文:WPF笔记(2.8 常用的布局属性)——Layout 这一节老没意思,啰里啰唆的尽是些HTML的属性,挑几个好玩的List出来,备忘:Padding与Margin的区别:Margin指控件边界与外界的间隙;Padding指的是控件内部内容与控件边界的间隙。
819 0