WPF: FishEyePanel/FanPanel - 自定义Panel
原文:WPF: FishEyePanel/FanPanel - 自定义Panel
原文来自CodeProject,主要介绍如何创建自定义的Panel,如同Grid和StackPanel。
1) Introduction
文中介绍了两种Panel:FishPanel(鱼眼面板,点击时当前面板变大,其它面板变小,但整体宽度不变),FanPanel(帆面板,不知如何翻译比较贴切,就这样吧;子面板位置,大小都可以改变,同样整体宽度不变)。
2)Using the Code
最低版本VS2005,.Net 3.0;
3)Writing a custom panel
创建自定义的窗体,需要从System.Windows.Controls.Panel派生新类,然后重写:MeasureOverride和LayoutOverride。在计算阶段,调用者可以确认它需要多大的空间;也帮助我们确认子控件的大小;接下来就是把最终的大小参数传递到ArrangeOverride方法;每次我们队Layout有改变时,上面的两步操作会重复发生的。
protected override Size MeasureOverride(Size availableSize)
{
Size idealSize = new Size(0, 0);
// Allow children as much room as they want - then scale them
Size size = new Size(Double.PositiveInfinity, Double.PositiveInfinity);
foreach (UIElement child in Children)
{
child.Measure(size);
idealSize.Width += child.DesiredSize.Width;
idealSize.Height = Math.Max(idealSize.Height,
child.DesiredSize.Height);
}
// EID calls us with infinity, but framework
// doesn't like us to return infinity
if (double.IsInfinity(availableSize.Height) ||
double.IsInfinity(availableSize.Width))
return idealSize;
else
return availableSize;
}
在MeasureOverride中,让子控件来决定我们所需的空间大小,这是通过属性Child.DesiredSize来获得的;接下来就是调整比例大小,使其适应整个窗体。
protected override Size ArrangeOverride(Size finalSize)
{
if (this.Children == null || this.Children.Count == 0)
return finalSize;
ourSize = finalSize;
totalWidth = 0;
foreach (UIElement child in this.Children)
{
// If this is the first time
// we've seen this child, add our transforms
if (child.RenderTransform as TransformGroup == null)
{
child.RenderTransformOrigin = new Point(0, 0.5);
TransformGroup group = new TransformGroup();
child.RenderTransform = group;
group.Children.Add(new ScaleTransform());
group.Children.Add(new TranslateTransform());
//group.Children.Add(new RotateTransform());
}
child.Arrange(new Rect(0, 0, child.DesiredSize.Width,
child.DesiredSize.Height));
totalWidth += child.DesiredSize.Width;
}
AnimateAll();
return finalSize;
}
在ArrangeOverride中,添加了比例计算,对每一个子控件都做变换,再统计总宽度;可以实现不同子控件变为相同宽度,或选择同样比例变成不同宽度,这是通过属性ScaleToFit来实现(代码中没看到?)。现在,我们只是把控件放在(0,0)处,接下来就是使用RenderTransoforms来移动控件。
鱼眼面板:设置3个子控件比其它的都大,所选哪3个控件是取决于当前鼠标的位置,其它的控件会填充余下的空间;
范面板:对子控件的旋转,缩放,平移来使控件以这三种方式排列:堆叠(stacked up),爆炸(exploded),包裹(wrap)
无论是鱼眼面板还是范面板,核心的处理过程都在AnimateAll(),可以查看它们的源代码。
4)Points of interest
无法在设计时直接以ItemControl方式显示,我们不能只指定一个名字就行,这是由于这两个控件只是一个模板,并不是真正的控件。作者想到了一个方法是:与Loaded事件相关联,然后把Sender转化为相关的面板模式。
为了演示界面效果,由于使用XPath和Binding不是很方便,作者使用了XmlDataProvider来加载所有图像。可在项目中先单独加载图像到一个Images文件夹,在TestData.xaml中我们看到:
<XmlDataProvider x:Key="Things" XPath="Things/Thing">
<x:XData>
<Things xmlns="">
<Thing Image="Aquarium.jpg"/>
<Thing Image="Ascent.jpg"/>
<Thing Image="Autumn.jpg"/>
<Thing Image="Crystal.jpg"/>
<Thing Image="DaVinci.jpg"/>
<Thing Image="Follow.jpg"/>
<Thing Image="Friend.jpg"/>
<Thing Image="Home.jpg"/>
<Thing Image="Moon flower.jpg"/>
</Things>
</x:XData>
</XmlDataProvider>
在App.xaml中引用这些资源,使它们在整个项目中都可见。
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/TestData.xaml" />
</ResourceDictionary.MergedDictionaries>
<local:ImagePathConverter x:Key="ImagePathConverter" />
</ResourceDictionary>
5)FishEye Panel Demo
5.1)设置界面背景色:
<Window.Background>
<ImageBrush ImageSource="Images/Azul.jpg" />
</Window.Background>
5.2)设置7行:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>
5.3)设置第二行:
<Border CornerRadius="10" Background="#99ffffff" Grid.Row="1">
<ItemsControl DataContext="{Binding Source={StaticResource Things}}" ItemsSource="{Binding}" Margin="0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:FishEyePanel Loaded="FishEye_Loaded" Magnification="3" AnimationMilliseconds="150" ScaleToFit="true"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<!-- This could obviously be any XAML. In our POC we dropped in entire UI pages and used it like a Vista taskbar -->
<Image Source="{Binding Converter={StaticResource ImagePathConverter}, XPath=@Image}" Width="{Binding XPath=@Width}" Margin="5"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Border>
上面设置了FishEyePanel的Loaded事件,及Image Source。
5.4)在主窗体cs文件中添加Loaded事件处理过程:
void FishEye_Loaded(object sender, RoutedEventArgs e)
{
fish = (FishEyePanel)sender;
}
5.5)演示界面(除去了后面两行的图像显示);点击其中的一张照片,左右的照片也一起变大,其余的照片不变;
实际上还有很多疑问,如不知如何改变图片的高度等。
附上FishEyePanel的源代码
5.6)FanPanel演示:默认状态
鼠标放在其上:
鼠标点击:
改变Detail Level值后的效果:
附上FanPanel的源代码。
WPF: FishEyePanel/FanPanel - 自定义Panel的更多相关文章
- 我的面板我做主 -- 淘宝UWP中自定义Panel的实现
在Windows10 UWP开发平台上内置的XMAL布局面板包括RelativePanel.StackPanel.Grid.VariableSizedWrapGrid 和 Canvas.在开发淘宝UW ...
- WPF中实现自定义虚拟容器(实现VirtualizingPanel)
WPF中实现自定义虚拟容器(实现VirtualizingPanel) 在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容 ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化)
原文:WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化) 注释直接写在代码里了 不太理解意思的 可以先去看看我上一篇 WPF ScrollViewer(滚动条) 自定 ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 再发一套样式 细节优化
艾尼路 出的效果图 本人嵌套 WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂 WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化) 源代码
- [WPF疑难] 继承自定义窗口
原文 [WPF疑难] 继承自定义窗口 [WPF疑难] 继承自定义窗口 周银辉 项目中有不少的弹出窗口,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于Window自身的,但每个弹出框 ...
- WPF编程,自定义鼠标形状的一种方法。
原文:WPF编程,自定义鼠标形状的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/details/8727 ...
- UWP开发入门(五)——自定义Panel
各位好,终于讲到自定义Panel了.当系统自带的几个Panel比如Gird,StackPanel,RelativePanel不能满足我们的特定要求时(其实不常见啦),自定义Panel就显得非常必要,而 ...
- 自定义Panel中添加依赖属性需要注意的问题
今天帮忙同事调试一个自定义Panel的问题, 很奇怪, 利用Binding可以通过ItemSource来添加控件,但是在Listbox的xaml里添加几个ListboxItem却报异常: Visual ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂
原文:WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂 先上效果图 正常样式 拖动时样式 好下面 开始吧 ==================================== ...
随机推荐
- 【物理/数学】概念的理解 —— pivot、position
0. 基本释义 pivot: n. 枢轴:中心点:旋转运动 vt. 以-为中心旋转:把-置于枢轴上 vi. 在枢轴上转动:随-转移 adj. 枢轴的:关键的 position: n. 位置,方位:职位 ...
- nas docker xunlei
http://bbs.xunlei.com/thread-389018-1-1.html 首先,启动远程服务,找到你的设备IP,在浏览器里输入以下地址,host换成你设备的IP http://host ...
- The DOT Language
CSDN新首页上线啦,邀请你来立即体验! 立即体验 博客 学院 下载 更多 登录注册 The DOT Language 翻译 2014年04月15日 11:27:07 标签: EBNF / 语言 / ...
- Xshell Update
http://blog.netsarang.com/1629/xshell-update-5-0-1332/ Xshell Update (5.0.1332) By Alan Kim Thursday ...
- 【u006】海战
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 在峰会期间,武装部队得处于高度戒备.警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞 ...
- 【b803】传纸条
Time Limit: 1 second Memory Limit: 50 MB [问题描述] 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...
- ajax 发送请求无法重定向问题
原因: ajax请求默认就是不支持重定向的,因为它是局部刷新,不重新加载页面. 解决方案: 开发中需要多处使用重定向的情况下,大多都是在Spring mvc 的拦截器中,或过滤器中使用,此方法是在sp ...
- js如何实现点击显示和隐藏表格
js如何实现点击显示和隐藏表格 一.总结 一句话总结: 1.给table或者table里面的元素添加点击事件, 2.然后判断当前表格的数据显示或者隐藏, 3.然后通过display属性显示(非none ...
- NOIP模拟 赌博游戏 - 概率dp
题意: 最近西雅图的高中校园里流行这样一个游戏. 我们有一个骰子,这个骰子有M个面,分别写着1..M,并且是个公平的骰子,换句话说,一次投掷时每个面朝上的概率是相同的. 游戏的组织者使用这个骰子进行N ...
- 小强的HTML5移动开发之路(33)—— jqMobi基础
一.什么是jqMobi jqMobi是由appMobi针对HTML5浏览器和移动设备开发的javascript框架,是个极快速的查询选择库,支持W3C查询. 版本 jqMobi源码最初在2012年1月 ...