У меня есть список, который динамически заполняется кодом.В некоторых случаях мне нужно поместить примечание, которое имеет другую высоту относительно других компонентов.Моя цель - сделать так, чтобы элементы Note и listview были обернуты вокруг, как в Word с изображением и Wrap Text, установленным в "Квадрат"
Я пыталсяиспользуйте UniformGrid и WrapPanel.Я пытался понять, как написать свою собственную WrapPanel, но я не нашел способ ее решить.Я думаю, что у меня может быть внешний компонент для заметки, и я могу оставить элементы списка, которые находятся под заметкой, например «Скрытый»
<ListView x:Name="PluginListView"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
SelectionMode="Single"
VerticalContentAlignment="Top"
BorderThickness="0"
Margin="0,10,0,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!--<UniformGrid Columns="4" HorizontalAlignment="Stretch" Rows="10"/>-->
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListView>
ДОБАВЛЕНО
Я создал пользовательскую сетку UniformGridЯ добавил свойство NoteRowToSkip, которое представляет строки для пропуска в последнем столбце слева.Я переопределил ArrangeOverride и добавил желаемое поведение пропуска.Отладка кажется, что значения правильные, но имеет то же поведение UniformGrid.
public class UniformNoteWrapGrid : Panel
{
private int m_Rows;
private int m_Columns;
public static readonly DependencyProperty NoteRowToSkipProperty = DependencyProperty.Register(nameof(NoteRowToSkip), typeof(int), typeof(UniformGrid), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateNoteRowToSkip);
private static bool ValidateNoteRowToSkip(object o)
{
return (int)o >= 0;
}
public int Columns
{
get => (int)GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.Register(
"Columns",
typeof(int),
typeof(UniformGrid),
new FrameworkPropertyMetadata(
0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateColumns);
private static bool ValidateColumns(object o)
{
return (int)o >= 0;
}
public int Rows
{
get => (int)GetValue(RowsProperty);
set => SetValue(RowsProperty, value);
}
public static readonly DependencyProperty RowsProperty =
DependencyProperty.Register("Rows", typeof(int),
typeof(UniformGrid),
new FrameworkPropertyMetadata(
0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateRows);
private static bool ValidateRows(object o)
{
return (int)o >= 0;
}
public int NoteRowToSkip
{
get => (int)GetValue(NoteRowToSkipProperty);
set => SetValue(NoteRowToSkipProperty, value);
}
protected override Size MeasureOverride(Size constraint)
{
UpdateComputedValues();
var childConstraint = new Size(constraint.Width / m_Columns, constraint.Height / m_Rows);
double maxChildDesiredWidth = 0.0;
double maxChildDesiredHeight = 0.0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
var child = InternalChildren[i];
child.Measure(childConstraint);
var childDesiredSize = child.DesiredSize;
if (maxChildDesiredWidth < childDesiredSize.Width)
maxChildDesiredWidth = childDesiredSize.Width;
if (maxChildDesiredHeight < childDesiredSize.Height)
maxChildDesiredHeight = childDesiredSize.Height;
}
return new Size(maxChildDesiredWidth * m_Columns, maxChildDesiredHeight * m_Rows);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
var childBounds = new Rect(0, 0, arrangeSize.Width / m_Columns, arrangeSize.Height / m_Rows);
double xStep = childBounds.Width;
double xBound = arrangeSize.Width - 1.0;
var row = 1;
var column = 1;
foreach (UIElement child in InternalChildren)
{
child.Arrange(childBounds);
if (child.Visibility == Visibility.Collapsed)
continue;
childBounds.X += xStep;
column++;
var testXBound = xBound;
if (IsCellForNote(row, column))
testXBound -= childBounds.Height;
if (!(childBounds.X >= testXBound))
continue;
childBounds.Y += childBounds.Height;
childBounds.X = 0;
row++;
column = 1;
}
return arrangeSize;
}
private bool IsCellForNote(int row, int column)
{
if (row > NoteRowToSkip)
return true;
return column != Columns;
}
private void UpdateComputedValues()
{
m_Columns = Columns;
m_Rows = Rows;
//if (FirstColumn >= m_Columns)
// FirstColumn = 0;
if (m_Rows != 0 && m_Columns != 0)
return;
int nonCollapsedCount = 0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
var child = InternalChildren[i];
if (child.Visibility != Visibility.Collapsed)
nonCollapsedCount++;
}
if (nonCollapsedCount == 0)
nonCollapsedCount = 1;
if (m_Rows == 0)
{
if (m_Columns > 0)
m_Rows = (nonCollapsedCount + (m_Columns - 1)) / m_Columns;
else
{
m_Rows = (int)Math.Sqrt(nonCollapsedCount);
if ((m_Rows * m_Rows) < nonCollapsedCount)
m_Rows++;
m_Columns = m_Rows;
}
}
else if (m_Columns == 0)
m_Columns = (nonCollapsedCount + (m_Rows - 1)) / m_Rows;
}
}
Есть идеи, что не работает в моем коде?
решено
Была проблема с условиями.Рабочая версия ниже.
public class UniformNoteWrapGrid : Panel
{
private int m_Rows;
private int m_Columns;
public static readonly DependencyProperty NoteRowToSkipProperty = DependencyProperty.Register(nameof(NoteRowToSkip), typeof(int), typeof(UniformGrid), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateNoteRowToSkip);
private static bool ValidateNoteRowToSkip(object o)
{
return (int)o >= 0;
}
public int Columns
{
get => (int)GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.Register(
"Columns",
typeof(int),
typeof(UniformGrid),
new FrameworkPropertyMetadata(
0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateColumns);
private static bool ValidateColumns(object o)
{
return (int)o >= 0;
}
public int Rows
{
get => (int)GetValue(RowsProperty);
set => SetValue(RowsProperty, value);
}
public static readonly DependencyProperty RowsProperty =
DependencyProperty.Register("Rows", typeof(int),
typeof(UniformGrid),
new FrameworkPropertyMetadata(
0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateRows);
private static bool ValidateRows(object o)
{
return (int)o >= 0;
}
public int NoteRowToSkip
{
get => (int)GetValue(NoteRowToSkipProperty);
set => SetValue(NoteRowToSkipProperty, value);
}
protected override Size MeasureOverride(Size constraint)
{
UpdateComputedValues();
var childConstraint = new Size(constraint.Width / m_Columns, constraint.Height / m_Rows);
double maxChildDesiredWidth = 0.0;
double maxChildDesiredHeight = 0.0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
var child = InternalChildren[i];
child.Measure(childConstraint);
var childDesiredSize = child.DesiredSize;
if (maxChildDesiredWidth < childDesiredSize.Width)
maxChildDesiredWidth = childDesiredSize.Width;
if (maxChildDesiredHeight < childDesiredSize.Height)
maxChildDesiredHeight = childDesiredSize.Height;
}
return new Size(maxChildDesiredWidth * m_Columns, maxChildDesiredHeight * m_Rows);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
var childBounds = new Rect(0, 0, arrangeSize.Width / m_Columns, arrangeSize.Height / m_Rows);
double xStep = childBounds.Width;
double xBound = arrangeSize.Width - 1.0;
var row = 1;
var column = 1;
foreach (UIElement child in InternalChildren)
{
child.Arrange(childBounds);
if (child.Visibility == Visibility.Collapsed)
continue;
childBounds.X += xStep;
column++;
var testXBound = xBound;
if (IsCellForNote(row, column))
testXBound -= xStep;
if (!(childBounds.X >= testXBound))
continue;
childBounds.Y += childBounds.Height;
childBounds.X = 0;
row++;
column = 1;
}
return arrangeSize;
}
private bool IsCellForNote(int row, int column)
{
if (row > NoteRowToSkip)
return false;
return column == Columns;
}
private void UpdateComputedValues()
{
m_Columns = Columns;
m_Rows = Rows;
//if (FirstColumn >= m_Columns)
// FirstColumn = 0;
if (m_Rows != 0 && m_Columns != 0)
return;
int nonCollapsedCount = 0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
var child = InternalChildren[i];
if (child.Visibility != Visibility.Collapsed)
nonCollapsedCount++;
}
if (nonCollapsedCount == 0)
nonCollapsedCount = 1;
if (m_Rows == 0)
{
if (m_Columns > 0)
m_Rows = (nonCollapsedCount + (m_Columns - 1)) / m_Columns;
else
{
m_Rows = (int)Math.Sqrt(nonCollapsedCount);
if ((m_Rows * m_Rows) < nonCollapsedCount)
m_Rows++;
m_Columns = m_Rows;
}
}
else if (m_Columns == 0)
m_Columns = (nonCollapsedCount + (m_Rows - 1)) / m_Rows;
}
}