Может ли WPF Listview иметь элемент с разной высотой, который встраивается в макет? - PullRequest
1 голос
/ 25 сентября 2019

У меня есть список, который динамически заполняется кодом.В некоторых случаях мне нужно поместить примечание, которое имеет другую высоту относительно других компонентов.Моя цель - сделать так, чтобы элементы Note и listview были обернуты вокруг, как в Word с изображением и Wrap Text, установленным в "Квадрат"

Layout

Я пыталсяиспользуйте 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;
        }
    }
...