【发布时间】:2014-02-21 14:51:51
【问题描述】:
我制作了一个自定义面板,类似于 WrapPanel,但带有列(或类似于 Grid,但项目会自动定位在网格中)。
这就是它的样子:
我想在我的面板上有一个属性,它在每列之间划一条线。是否可以在自定义面板上绘图?
我正在寻找的结果是这样的(注意黑线):
编辑:如果我使窗口更宽,面板将自动创建更多列,因此分隔线必须是动态的 - 也就是说,它可能是零、一、二、三或更多分隔线。
这是我的面板的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication26
{
public class AutoSizingColumnsWrapPanel : Panel
{
public double MinColumnWidth { get; set; }
//public bool ShowColumnSeparator { get; set; }
public AutoSizingColumnsWrapPanel()
{
MinColumnWidth = 100;
}
protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
{
return DoLayout(availableSize, (uiElement, size, pos) => uiElement.Measure(size));
}
protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
{
return DoLayout(finalSize, (uiElement, size, pos) => uiElement.Arrange(pos));
}
private Size DoLayout(Size availableSize, Action<UIElement, Size, Rect> layoutAction)
{
// Calculate number of columns and column width
int numberOfColumns = 0;
double columnWidth = MinColumnWidth;
if (double.IsInfinity(availableSize.Width))
{
numberOfColumns = InternalChildren.Count;
}
else
{
numberOfColumns = (int)Math.Max(Math.Floor(availableSize.Width / MinColumnWidth), 1);
columnWidth = availableSize.Width / numberOfColumns;
}
// Init layout parameters
Size measureSize = new Size(columnWidth, availableSize.Height);
int currentColumn = 0;
int currentRow = 0;
double currentY = 0;
double currentRowHeight = 0;
// Place all items.
foreach (UIElement item in InternalChildren)
{
var position = new Rect(currentColumn++ * columnWidth, currentY, columnWidth, item.DesiredSize.Height);
// Execute action passing: item = The child item to layout | measureSize = The size allocated for the child item | position = The final position and height of the child item.
layoutAction(item, measureSize, position);
// Keep the highest item on the row (so that we know where to start the next row).
currentRowHeight = Math.Max(currentRowHeight, item.DesiredSize.Height);
if (currentColumn == numberOfColumns)
{
// The item placed was in the last column. Increment/reset layout counters.
currentRow++;
currentColumn = 0;
currentY += currentRowHeight;
currentRowHeight = 0;
}
}
// Return total size of the items/panel.
return new Size(numberOfColumns * columnWidth, currentY + currentRowHeight);
}
}
}
这是我托管面板的 WPF 窗口:
<Window x:Class="WpfApplication26.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication26"
Title="MainWindow" Height="350" Width="525">
<local:AutoSizingColumnsWrapPanel MinColumnWidth="200" VerticalAlignment="Top">
<TextBlock Text="One" Background="AliceBlue"/>
<DockPanel >
<TextBlock Text="Two: " Background="Beige"/>
<TextBox HorizontalAlignment="Stretch" />
</DockPanel>
<TextBlock Text="Three" Background="DarkKhaki"/>
<TextBlock Text="Four" Background="AliceBlue"/>
<TextBlock Text="Five" Background="Beige" Height="50"/>
<TextBlock Text="Six" Background="DarkKhaki"/>
<TextBlock Text="Seven" Background="AliceBlue"/>
<TextBlock Text="Eight" Background="Beige"/>
<TextBlock Text="Nine" Background="DarkKhaki"/>
<TextBlock Text="Ten" Background="AliceBlue"/>
<TextBlock Text="Eleven" Background="Beige"/>
</local:AutoSizingColumnsWrapPanel>
</Window>
【问题讨论】:
-
应该可以通过将文本块的边框粗细设置为
BorderThickness="0,0,1,0" -
@ywm 抱歉,如果我不清楚我正在寻找一种无需修改面板内容的解决方案。无论我在面板中放置什么,我都希望面板绘制线条。
-
在这种情况下,您可以在面板上设置边框厚度。
-
@ywm 感谢您的建议,但我希望在每列之间出现一条垂直线(如第二张图片所示)。无论如何,我想我可以通过绘制 OnRender 方法来完成它。