原文: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谢谢

WPF中的 Layout To Layout的更多相关文章

  1. WPF笔记(2.4 Grid)——Layout

    原文:WPF笔记(2.4 Grid)--Layout 第一章已经简单介绍过这个容器,这一节详细介绍.Grid一般是用表格(Grid.Row 和Grid.Column )的,比StackPanel更细致 ...

  2. WPF笔记(2.2 DockPanel)——Layout

    原文:WPF笔记(2.2 DockPanel)--Layout 读完了这一节,发现DockPanel就是过去winform中的Dock属性.原来的Dock属性是子控件设置,而其父亲级别不用设置.现在W ...

  3. WPF笔记(2.5 Canvas)——Layout

    原文:WPF笔记(2.5 Canvas)--Layout Canvas是最精确的布局容器--绝对定位,此书作者不建议使用,以为控件的大小一般会随着内部字体图片的动态生成而自动变化,所以使用前三种布局是 ...

  4. WPF笔记(2.6 ViewBox)——Layout

    原文:WPF笔记(2.6 ViewBox)--Layout 在Canvas外面包一层ViewBox,可以使Canvas内的控件填充整个ViewBox,并随着ViewBox的大小变化而同步变化,这是因为 ...

  5. WPF笔记(2.3 StackPanel)——Layout

    原文:WPF笔记(2.3 StackPanel)--Layout StackPanel用于小规模的排版布局,比如说一个局部下几个textbox和Button啦.Orientation属性有Vertic ...

  6. flutter系列之:flutter中常用的container layout详解

    目录 简介 Container的使用 旋转Container Container中的BoxConstraints 总结 简介 在上一篇文章中,我们列举了flutter中的所有layout类,并且详细介 ...

  7. WPF中log4net的用法

    WPF中如何使用log4nethttp://www.cnblogs.com/C-Sharp2/archive/2013/04/12/WPF-LOG4NET.html Apache log4net Ma ...

  8. 在WPF中自定义你的绘制(二)

    原文:在WPF中自定义你的绘制(二)   在WPF中自定义你的绘制(二)                                                                 ...

  9. wpf中的样式与模板

    1.WPF样式类似于Web应用程序中的CSS,在WPF中可以为控件定义统一的样式(Style).样式属于资源的一种,例如为Button定义统一的背景颜色和字体: <Window.Resource ...

随机推荐

  1. mybatis逆向工程随笔

    mybatis框架简介和简单原理: mybatis本来是apache的一个开源的项目,后来迁移到了google,并且改名为mybatis. mybatis框架优点: 1.mybatis是最简单的持久化 ...

  2. Eclipse 快捷键大全 分类: C_OHTERS 2014-06-01 13:05 332人阅读 评论(0) 收藏

      精选常用: 1.  ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如a ...

  3. VS2008的C++TR1库已经支持正则表达式

    作者:朱金灿 来源:http://blog.csdn.net/clever101 发现VS2008的C++ TR1库已经支持正则表达式了(注意装了VS 2008sp1采用TR1库的).下面简单做个测试 ...

  4. Sub-process /usr/bin/dpkg returned an error code (1)错误解决办法

    之前通过wine安装了一款软件,不经常用,也没有拆卸 可是之后呢,每次更新都要提示更新那个软件,更新的时候又总是找不到更新源 无奈之下,我通过软件中心移除wine,没想到竟然碰到依赖问题,没有拆卸成功 ...

  5. js如何使用正则表达式验证电话号码(可选区号)和邮箱?(分步骤)

    js如何使用正则表达式验证电话号码(可选区号)和邮箱?(分步骤) 一.总结 js进阶正则表达式16电话号码和邮箱正则(分类解决邮箱验证)(分组加?解决电话号码区号选择问题)([\w\.-]中括号解决邮 ...

  6. Qt 静态函数QMetaObject::connectSlotsByName(QObject * object)

    看别人代码看到void on_MyWidget_slotTest(); 就郁闷了,没看到他代码里有connect 却能把信号和槽可以连接起来. 今日回顾书本发现该函所的nb之处. QMetaObjec ...

  7. 对Fragment切换的优化

    在项目中需要进行Fragment的切换,一直都是用replace()方法来替换Fragment:然后总感觉切换的时候有些卡顿,原来的代码 /** * 切换页面,这里采用回调 * * @param f ...

  8. [SVG] Optimize SVGs for Better Performance using svgo

    Just like a bitmap image, you can compress an SVG by removing various pieces of code that aren’t nec ...

  9. 解决离线Could not parse configuration:hibernate.cfg.xml错误

    离线使用hibernate tool 生成反向工程,在配置 配置文件完,生成配置文件后,会报出org.hibernate.HibernateException: Could not parse con ...

  10. 【BZOJ 1019】 [SHOI2008]汉诺塔

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1019 [题意] [题解] 这个题解讲得很清楚了 http://blog.sina.co ...