Построение обратимой StackPanel в WPF
Я хотел бы создать пользовательский StackPanel
С ReverseOrder
свойство, которое я могу декларативно установить в true, чтобы элементы в StackPanel отображались в порядке, противоположном нормальному (например, снизу вверх или справа налево). Он должен быть обратимым "на лету".
Я думаю о получении нового класса из StackPanel, но мне нужно знать, какие методы переопределить.
окончательное решение:
protected override System.Windows.Size ArrangeOverride( System.Windows.Size arrangeSize ) {
double x = 0;
double y = 0;
IEnumerable<UIElement> children = ReverseOrder ? InternalChildren.Cast<UIElement>().Reverse<UIElement>() : InternalChildren.Cast<UIElement>();
foreach ( UIElement child in children ) {
var size = child.DesiredSize;
child.Arrange( new Rect( new Point( x, y ), size ) );
if ( Orientation == Orientation.Horizontal )
x += size.Width;
else
y += size.Height;
}
if ( Orientation == Orientation.Horizontal )
return new Size( x, arrangeSize.Height );
else
return new Size( arrangeSize.Width, y );
}
также определить и зарегистрировать ReverseOrder
и звоните UpdateLayout
если он изменяет.
3 ответов
вы можете переопределить FrameworkElement.ArrangeOverride и вызвать все дочерние.Организовать в обратном порядке, чем обычно, когда это необходимо.
http://msdn.microsoft.com/en-us/library/system.windows.uielement.arrange.aspx
что-то вроде этого (не проверял):
double x = 0;
double y = 0;
var children = ReverseOrder ? InternalChildren.Reverse() : InternalChildren;
foreach (UIElement child in children)
{
var size = child.DesiredSize;
child.Arrange(new Rect(new Point(x, y), size));
if (Orientation == Horizontal)
x += size.Width;
else
y += size.Height;
}
убедитесь, что вы вызываете UpdateLayout после изменения свойства ReverseOrder.
MeasureOverride и ArrangeOverride
на самом деле ваша логика измерения может совпадать с StackPanel, поэтому вы можете просто переопределить ArrangeOverride. Имейте в виду, что StackPanel имеет некоторую логику для обработки прокрутки, которую вам может потребоваться дублировать, если вы пишете ее самостоятельно. Вы можете наследовать непосредственно из панели и не пытаться поддерживать прокрутку.
посмотреть Пользовательские Элементы Панели на странице MSDN на панелях или различные записи в блоге о написании пользовательских панелей, таких как учебник WPF-создание пользовательского элемента управления панели или создание пользовательских панелей в WPF.
вот еще один вариант. Он основан на StackPanel
' s источник и может общаться с выравниваниями деталя также.
public class ReversibleStackPanel : StackPanel
{
public bool ReverseOrder
{
get => (bool)GetValue(ReverseOrderProperty);
set => SetValue(ReverseOrderProperty, value);
}
public static readonly DependencyProperty ReverseOrderProperty =
DependencyProperty.Register(nameof(ReverseOrder), typeof(bool), typeof(ReversibleStackPanel), new PropertyMetadata(false));
protected override Size ArrangeOverride(Size arrangeSize)
{
bool fHorizontal = (Orientation == Orientation.Horizontal);
var rcChild = new Rect(arrangeSize);
double previousChildSize = 0.0;
var children = ReverseOrder ? InternalChildren.Cast<UIElement>().Reverse() : InternalChildren.Cast<UIElement>();
foreach (UIElement child in children)
{
if (child == null)
continue;
if (fHorizontal)
{
rcChild.X += previousChildSize;
previousChildSize = child.DesiredSize.Width;
rcChild.Width = previousChildSize;
rcChild.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height);
}
else
{
rcChild.Y += previousChildSize;
previousChildSize = child.DesiredSize.Height;
rcChild.Height = previousChildSize;
rcChild.Width = Math.Max(arrangeSize.Width, child.DesiredSize.Width);
}
child.Arrange(rcChild);
}
return arrangeSize;
}
}