我制作了一个自定义面板,类似于 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 layoutAction)
{
// Calculate number of columns and column width
int numberOfColumns = 0;
double columnWidth = MinColumnWidth;
if (double.IsInfinity(availableSize.Width))
{
numberOfColumns = InternalChildren.Count;
}
khác
{
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 窗口:
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">
我发现我可以覆盖面板中的 OnRender 方法。 OnRender 方法为我提供了一个 DrawingContext,它允许我绘制线条(和其他形状)。
我做了一个快速而肮脏的测试,并通过一些修改我认为我可以让它工作。
如果有人需要了解它的工作原理,这里是快速代码:
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
var pen = new System.Windows.Media.Pen(System.Windows.Media.Brushes.Black, 2);
for (int i = 0; i < _numberOfColumns; i++)
{
double x = (i + 1) * _columnWidth;
dc.DrawLine(pen, new Point(x, 0), new Point(x, 1000));
}
base.OnRender(dc);
}
我会尽量记得在完成后发布完整的代码。
Tôi là một lập trình viên xuất sắc, rất giỏi!