如何创建一个WrapPanel,其中某些项的高度为*?
这是一个看似简单但我一直在尝试解决的问题。我想要一个类似于Grid的控件(或者一些XAML布局魔法),它可以像Grid一样设置一些行的高度为*,但同时支持列的换行。甚至可以称之为WrapGrid。
以下是一个模拟图以帮助理解。请想象一个定义如下的网格:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" MinHeight="30">I'm auto-sized.</Button>
<Button Grid.Row="1" MinHeight="90">I'm star-sized.</Button>
<Button Grid.Row="2" MinHeight="30">I'm auto-sized.</Button>
<Button Grid.Row="3" MinHeight="90">I'm star-sized, too!</Button>
<Button Grid.Row="4" MinHeight="30">I'm auto-sized.</Button>
<Button Grid.Row="5" MinHeight="30">I'm auto-sized.</Button>
</Grid>
</Window>
我希望这个面板能够在项的最小高度无法再缩小时,将该项包装到另一列中。以下是我制作的一些模型的可怕MSPaint详细说明此过程。
从XAML中可以看出,自动调整大小的按钮具有最小高度为30,而星号调整大小的按钮具有最小高度为90。这个模拟只是将两个网格并排放置,并手动在设计师中移动按钮。理论上,这可以通过编程来完成,并作为一种解决方案。
如何做到这一点?我将接受任何解决方案,无论是通过xaml还是具有一些代码后台(尽管我更喜欢纯粹的XAML,如果可能的话,因为在IronPython中实现xaml代码后台更加困难)。
使用悬赏更新。
Meleak的解决方案
我成功地找出了如何在我的IPy应用程序中使用Meleak的解决方案:
1)我使用csc
将WrapGridPanel.cs
编译成DLL:
C:\Projects\WrapGridTest\WrapGridTest>csc /target:library "WrapGridPanel.cs" /optimize /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationCore.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\WindowsBase.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xaml.dll"
更新: 添加了/optimize
开关,这将带来小幅的性能提升。
2) 我在应用程序的XAML中添加了以下代码。
xmlns:local="clr-namespace:WrapGridTest;assembly=WrapGridPanel.dll"
这段代码可以正常运行,但会导致设计器出现问题。目前我还没有找到解决办法,看起来是VS2010的一个bug。因此,为了能够使用设计器,我只能在运行时通过编程方式添加WrapGridPanel作为临时解决方法:
clr.AddReference("WrapGridPanel.dll")
from WrapGridTest import WrapGridPanel
wgp = WrapGridPanel()
调整大小时性能缓慢:
在我的IronPython应用程序中,调整包含此WrapGridPanel的窗口的大小很慢且不流畅。 RecalcMatrix()
算法是否可以进行优化?它可能被调用得更少吗?也许像Nicholas建议的那样覆盖MeasureOverride
和ArrangeOverride
会更好?
更新: 根据VS2010 Instrumentation Profiler,RecalcMatrix()中花费的时间有97%用于Clear()和Add()。 在原地修改每个元素将大大提高性能。 我正在尝试自己解决,但修改别人的代码总是很困难... http://i.stack.imgur.com/tMTWU.png
更新:性能问题已经基本解决。谢谢Meleak!
这是我实际应用程序UI的部分XAML模型,如果您想尝试一下。 http://pastebin.com/2EWY8NS0