gpt4 book ai didi

wpf - 具有覆盖的 OnVisualChildrenChanged 的​​自定义 WPF WrapPanel 将无法按预期工作

转载 作者:行者123 更新时间:2023-12-04 03:10:32 24 4
gpt4 key购买 nike

我正在 Windows 上开发一个应用程序,我想要一个像这样布局其子项的面板:

This is my desired layout

我在 WPF 面板中找到的最接近的是垂直方向的 WrapPanel,其布局如下:

This is WrapPanel (with vertical orientation) layout

到目前为止,我的解决方案是从 WrapPanel 创建派生类并将其及其每个子级旋转 180 度,以便实现我的目标:

public class NotificationWrapPanel : WrapPanel
{
public NotificationWrapPanel()
{
this.Orientation = Orientation.Vertical;
this.RenderTransformOrigin = new Point(.5, .5);
this.RenderTransform = new RotateTransform(180);
}
protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
{
var addedChild = visualAdded as UIElement;
if (addedChild != null)
{
addedChild.RenderTransformOrigin = new Point(.5, .5);
addedChild.RenderTransform = new RotateTransform(180);
}

base.OnVisualChildrenChanged(addedChild, visualRemoved);
}
}

问题是被覆盖的 OnVisualChildrenChanged 中的 addedChild.RenderTransform = new RotateTransform(180) 部分似乎不起作用。欢迎任何解决方案(即使与我的方法无关)。

更新:

我重新检查了我的代码并意识到我在其他地方更改了 RenderTransform,从而阻止了它的工作。所以我的问题解决了。但是,如果您提供任何可能更优雅的解决方案,我将不胜感激,例如使用 MeasureOverride/ArrangeOverride

最佳答案

根据您的要求,下面是一个自定义面板,我认为它应该可以满足您的需求。它以从下到上然后从右到左的方式排列子元素,在一列中堆叠最多 MaxRows 个元素(或者所有元素,如果它是 null)。所有插槽的大小都相同。它还确实考虑了元素的 Visibility 值,即如果一个项目是 Hidden,它会留下一个空槽,如果它是 Collapsed ,它被跳过,下一个元素“跳”到它的位置。

public class NotificationWrapPanel : Panel
{
public static readonly DependencyProperty MaxRowsProperty =
DependencyProperty.Register(
name: nameof(MaxRows),
propertyType: typeof(int?),
ownerType: typeof(NotificationWrapPanel),
typeMetadata: new FrameworkPropertyMetadata
{
AffectsArrange = true,
AffectsMeasure = true,
},
validateValueCallback: o => o == null || (int)o >= 1);

public int? MaxRows
{
get { return (int?)GetValue(MaxRowsProperty); }
set { SetValue(MaxRowsProperty, value); }
}

protected override Size MeasureOverride(Size constraint)
{
var children = InternalChildren
.Cast<UIElement>()
.Where(e => e.Visibility != Visibility.Collapsed)
.ToList();
if (children.Count == 0) return new Size();
var rows = MaxRows.HasValue ?
Math.Min(MaxRows.Value, children.Count) :
children.Count;
var columns = children.Count / rows +
Math.Sign(children.Count % rows);
var childConstraint = new Size
{
Width = constraint.Width / columns,
Height = constraint.Height / rows,
};
foreach (UIElement child in children)
child.Measure(childConstraint);
return new Size
{
Height = rows * children
.Cast<UIElement>()
.Max(e => e.DesiredSize.Height),
Width = columns * children
.Cast<UIElement>()
.Max(e => e.DesiredSize.Width),
};
}

protected override Size ArrangeOverride(Size finalSize)
{
var children = InternalChildren
.Cast<UIElement>()
.Where(e => e.Visibility != Visibility.Collapsed)
.ToList();
if (children.Count == 0) return finalSize;
var rows = MaxRows.HasValue ?
Math.Min(MaxRows.Value, children.Count) :
children.Count;
var columns = children.Count / rows +
Math.Sign(children.Count % rows);
var childSize = new Size
{
Width = finalSize.Width / columns,
Height = finalSize.Height / rows
};
for (int i = 0; i < children.Count; i++)
{
var row = i % rows; //rows are numbered bottom-to-top
var col = i / rows; //columns are numbered right-to-left
var location = new Point
{
X = finalSize.Width - (col + 1) * childSize.Width,
Y = finalSize.Height - (row + 1) * childSize.Height,
};
children[i].Arrange(new Rect(location, childSize));
}
return finalSize;
}
}

关于wpf - 具有覆盖的 OnVisualChildrenChanged 的​​自定义 WPF WrapPanel 将无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45659206/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com