Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84

Методы ArrangeOverride и MeasureOverride для позиционирования элементов

10.01.2020, 14:50. Показов 2273. Ответов 33

Студворк — интернет-сервис помощи студентам
Добрый день, народ! В чем проблема не знаю как правильно позиционировать элементы в Panel и достичь аналогичного результата как на картинке слева. Думаю, что надо раскурочить методы ArrangeOverride и MeasureOverride, но не знаю как(((
Может кто сталкивался или подскажет куда копать?

Методы ArrangeOverride и MeasureOverride в классе VirtualizingWrapPanel
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/// <summary>
        /// Measure the children
        /// </summary>
        /// <param name="availableSize">Size available</param>
        /// <returns>Size desired</returns>
        protected override Size MeasureOverride(Size availableSize) {
            try {
                this.UpdateScrollInfo(availableSize);
 
                // Figure out range that's visible based on layout algorithm
                int firstVisibleItemIndex = 0;
                int lastVisibleItemIndex = 0;
                GetVisibleRange(ref firstVisibleItemIndex, ref lastVisibleItemIndex);
 
                // We need to access InternalChildren before the generator to work around a bug
                UIElementCollection children = this.InternalChildren;
                IItemContainerGenerator generator = this.ItemContainerGenerator;
 
                // Get the generator position of the first visible data item
                GeneratorPosition startPos = generator.GeneratorPositionFromIndex(firstVisibleItemIndex);
 
                // Get index where we'd insert the child for this position. If the item is realized
                // (position.Offset == 0), it's just position.Index, otherwise we have to add one to
                // insert after the corresponding child
                int childIndex = (startPos.Offset == 0) ? startPos.Index : startPos.Index + 1;
 
                using (generator.StartAt(startPos, GeneratorDirection.Forward, true)) {
                    int itemIndex = firstVisibleItemIndex;
                    while (itemIndex <= lastVisibleItemIndex) {
                        bool newlyRealized = false;
 
                        // Get or create the child
                        UIElement child = generator.GenerateNext(out newlyRealized) as UIElement;
                        if (newlyRealized) {
                            // Figure out if we need to insert the child at the end or somewhere in the middle
                            if (childIndex >= children.Count) {
                                base.AddInternalChild(child);
                            } else {
                                base.InsertInternalChild(childIndex, child);
                            }
                            generator.PrepareItemContainer(child);
                        } else {
                            // The child has already been created, let's be sure it's in the right spot
                            Debug.Assert(child.Equals(children[childIndex]), "Wrong child was generated");
                        }
 
                        // Measurements will depend on layout algorithm
                        child.Measure(GetChildSize());
                        itemIndex += 1;
                        childIndex += 1;
                    }
                }
 
                // Note: this could be deferred to idle time for efficiency
                CleanUpItems(firstVisibleItemIndex, lastVisibleItemIndex);
            } catch (ArgumentOutOfRangeException) {
                // No idea if we can ignore this
            } catch (NullReferenceException) {
                // No idea if we can ignore this
            }
 
            // Guard against possible infinity if exiting measure early
            return new Size(double.IsInfinity(availableSize.Width) ? 0 : availableSize.Width, double.IsInfinity(availableSize.Height) ? 0 : availableSize.Height);
        }
 
        /// <summary>
        /// Arrange the children
        /// </summary>
        /// <param name="finalSize">Size available</param>
        /// <returns>Size used</returns>
        protected override Size ArrangeOverride(Size finalSize) {
            IItemContainerGenerator generator = this.ItemContainerGenerator;
 
            UpdateScrollInfo(finalSize);
 
            for (int i = 0; i <= this.Children.Count - 1; i++) {
                UIElement child = this.Children[i];
 
                // Map the child offset to an item offset
                int itemIndex = generator.IndexFromGeneratorPosition(new GeneratorPosition(i, 0));
 
                ArrangeChild(itemIndex, child, finalSize);
            }
 
            return finalSize;
        }

Вот использую
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ListBox x:Name="list" 
                 ItemsSource="{Binding Photos}" 
                 SelectedItem="{Binding Photo}"
                 ScrollViewer.IsDeferredScrollingEnabled="True"
                 VirtualizingStackPanel.IsVirtualizing="True"
                 VirtualizingStackPanel.VirtualizationMode="Recycling"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderBrush="Transparent" Foreground="Transparent">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <control:VirtualizingWrapPanel/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Image Source="{Binding Image}"  Stretch="UniformToFill" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
Миниатюры
Методы ArrangeOverride и MeasureOverride для позиционирования элементов   Методы ArrangeOverride и MeasureOverride для позиционирования элементов  
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.01.2020, 14:50
Ответы с готовыми решениями:

Позиционирования элементов
Здравствуйте, я новичек в C# и вообще в .NET. Создаю форму, располагаю элементы, но при изменении формы открытрй программы они остаются на...

Есть ли функция для резервации определенного места на сайте для постоянного позиционирования элемента?
Bootstrap NAVBAR (HOME FOTO) на сайте имеет класс sticky (приклееный), т.е. он прокручивается вместе с сайтом. Но во время прокрутки он...

Использование z-index для позиционирования блоков
Здравствуйте! Помогаю знакомым делать лабораторную по HTML. В ней есть задание: нарисовать большой зелёный квадрат с белым текстом. На...

33
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
11.01.2020, 18:52
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Unsafe Посмотреть сообщение
Так как хотел сделать как Google Фото
Я не пойму почему на варианте Google Фото строки разного размера?
Я не пользуюсь этим приложением.
0
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84
11.01.2020, 19:01  [ТС]
Да они разные! Только в рамках группировки одинаковые.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 00:54
Цитата Сообщение от Unsafe Посмотреть сообщение
Да они разные! Только в рамках группировки одинаковые.
Мне не понятен алгоритм определения высоты строки
0
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84
12.01.2020, 15:05  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Мне не понятен алгоритм определения высоты строки
Алгоритм в Google Фото или в VirtualizingWrapPanel?
Google Фото я думаю, что там иначе все построено, так как это вебсайт и там другие компоненты верстки, но если попытаться реализовать на WPF наверное надо смотреть ListView с группировкой по дате и VirtualizingWrapPanel , а ItemTemplate это еще один ListView без группировки на VirtualizingWrapPanel. Блин это еще те танцы с бубнами, потом бороться с производительностью не понятно как это себя поведет, но можно попробовать.
Кстати на счет производительности нашел реализованный VirtualizingObservableCollection https://www.nuget.org/packages... ollection/ еще не опробовал, так как придется пару моих классов переписать по загрузке изображений. Превосходство в том, что я и хотел LazyLoad о преимуществах данного подхода думаю не стоит говоить
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 15:14
Цитата Сообщение от Unsafe Посмотреть сообщение
Алгоритм в Google Фото или в VirtualizingWrapPanel?
И там, и там.

По высоте исходных изображений в строке? Явно нет - они много больше.

Что берётся за высоту строки?

Если это задать, то остальное упрощается. У всех Image в строке привязать высоту к этому значению. А ширину ограничить каким-нибудь пропорциональным значением.

Получатся все изображения одной высоты. Ширина согласно исходным пропорциям, но не более заданной.

Добавлено через 1 минуту
Цитата Сообщение от Unsafe Посмотреть сообщение
Превосходство в том, что я и хотел LazyLoad о преимуществах данного подхода думаю не стоит говорить
В ListBox, по моему, это и так реализовано по умолчанию.
Не проверял, но так понял документацию.
0
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84
12.01.2020, 15:21  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В ListBox, по моему, это и так реализовано по умолчанию.
Смотрел я это и тестил 10 000 изображений как наповал прут, да реализация асинхронной загрузки спасает и плавное перематывание, и не зависание интерфейса, но в отладчике смотришь на объем памяти, а он растет, что не является правильным.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 15:31
Цитата Сообщение от Unsafe Посмотреть сообщение
Смотрел я это и тестил 10 000 изображений как наповал прут
Как проверяли?
Загрузили в ListBox 10 000 ссылок на изображения.
В его шаблоне элемента ссылка визуализируется через привязку в Image.
В окно выводится первые 10 элементов.
Но по факту, он грузит сразу все 10_000 элементов.

Так было?

Или память начинает "съедаться" после скрулла по ListBox?
0
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84
12.01.2020, 15:31  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В ListBox, по моему, это и так реализовано по умолчанию.
Вот блин, а я мучился вообщем вот, что значит торопиться))) изначально был ListBox, но пока я тестил разные виртуализации изменил на Listview и естественно не получал необходимого результата, а теперь 372 мб памяти при развернутом виде окна около 650 мб
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 15:35
Цитата Сообщение от Unsafe Посмотреть сообщение
пока я тестил разные виртуализации изменил на Listview
У ListView и DataGrid виртуализация с ленивой загрузкой тоже, по моему, по умолчанию с "коробки" идёт.
0
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84
12.01.2020, 15:42  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
ListView
Толи меня система обманула, но как, то странно повела сейчас опять ползет вверх память еще раз закинул свои картинки и до 1 Гб дошел, дальше не стал смотреть это уже много!
Вот что MSDN пишет
Создание большого количества элементов пользовательского интерфейса, если на экране может быть недостаточное количество элементов, может негативно сказаться на производительности приложения. VirtualizingStackPanel Например, выражение ListBox ItemContainerGenerator ListViewвычисляет количество видимых элементов и работает с элементом from (например, или) для создания элементов пользовательского интерфейса только для видимых элементов. ItemsControl
Так что необходимо использовать VirtualizingStackPanel, но так как там компоновка в один столбец или строку, то пишут кастомный VirtualizingWrapPanel, какой у меня и кстати это самый приличный, что видел другие реализации полный трэш, тормозит, дергается и т.д.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 15:44
Там же суть в чём.
Элемент визуализируется только когда он в видимой части окна.
Как он визуализируется задаётся шаблоном данных.

Поэтому если в источнике находятся ссылки на изображения, то ничего кроме этих ссылок не грузится.
Сами ссылки и память под них задаётся в VM.

LisBox (ListView и DataGrid) те ссылки которые должны быть отображены визуализирует используя шаблон.
Получает по этому шаблону Image.

Если уходит ссылка с экрана, то её Image сразу выгружается.
Это можно проверить добавив обработчики Image.Loaded и Image.Unloaded.

А вот если вы создаёте список не ссылок, а изображений, то здесь конечно нужная "ручная" настройка ленивой загрузки.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 15:53
Цитата Сообщение от Unsafe Посмотреть сообщение
странно повела сейчас опять ползет вверх память еще раз закинул свои картинки и до 1 Гб
Но это и есть принцип работы ленивой загрузки.
Когда элемент не нужен убирается сильная ссылка на него.
Но сам он остаётся в памяти.
Если системе нужна память под что-то другое, она отправляет сборщика мусора.
Сборщик очищает не всю память сразу.
Он чистит по мере необходимости в свободной памяти.

Сначала за счёт объектов на которых вообще нет ссылок.
Потом за счёт тек на которых есть слабые ссылки, но нет сильных.

Когда обращаетесь к объекту по слабой ссылки, проверяется его наличие в памяти.
Если мусорщик ещё память под объект не очистил, то сразу возвращается сильная ссылка на этот объект.
Если очистил, то объект заново грузится.

Поэтому при использовании слабых ссылок память процесса будет расти.
Но насколько это зависит от того как позволит система.
0
11 / 9 / 5
Регистрация: 09.10.2019
Сообщений: 84
12.01.2020, 16:00  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
а изображений, то здесь конечно нужная "ручная"
Вы как мои мысли читаете, убираю привязку к Image и ставлю на Uri 5 минут и отпишусь о результате

Добавлено через 4 минуты
Все равно заполняет память без остановки. Из VM я убрал вообще ImageSource Image остался только Uri
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<ListBox x:Name="list" 
                  ItemsSource="{Binding Photos}" 
                 VirtualizingPanel.IsVirtualizing="True"
                 VirtualizingPanel.IsContainerVirtualizable="True"
                  VirtualizingPanel.VirtualizationMode="Recycling"
                  VirtualizingPanel.CacheLengthUnit="Page"
                  VirtualizingPanel.CacheLength="1,1"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderBrush="Transparent" Foreground="Transparent">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image Stretch="None">
                        <Image.Source>
                            <BitmapImage UriSource="{Binding Uri}" DecodePixelHeight="170"/>
                        </Image.Source>
                    </Image>
                </DataTemplate>
            </ListBox.ItemTemplate>
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.01.2020, 16:23
Цитата Сообщение от Unsafe Посмотреть сообщение
Все равно заполняет память без остановки. Из VM я убрал вообще ImageSource Image остался только Uri
Вы по-моему создаёте лишние объекты.
И добавьте обработчики загрузки и выгрузки.
Проверьте как загружаются/выгружаются Image
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        <ListBox x:Name="list" 
                  ItemsSource="{Binding Photos}" 
                 VirtualizingPanel.IsVirtualizing="True"
                 VirtualizingPanel.IsContainerVirtualizable="True"
                  VirtualizingPanel.VirtualizationMode="Recycling"
                  VirtualizingPanel.CacheLengthUnit="Page"
                  VirtualizingPanel.CacheLength="1,1"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderBrush="Transparent" Foreground="Transparent">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image Stretch="None" Source="{Binding Uri}"
                           Loaded="Image_Loaded"
                           Unloaded="Image_Unloaded"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
Добавлено через 1 минуту
По идее, когда изображение уйдёт с экрана оно должно выгрузится.
Но возможно не сразу - это зависит от системы и её потребности в памяти.

Добавлено через 14 минут
Unsafe, я проверил у себя на простом примере
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    <Grid>
        <ListBox x:Name="list" 
                 ItemsSource="{Binding FilesNames}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Green" BorderThickness="1" Padding="2">
                        <Image Source="{Binding}"  Stretch="UniformToFill" 
                               Loaded="Image_Loaded"
                               Unloaded="Image_Unloaded"/>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button VerticalAlignment="Bottom" HorizontalAlignment="Center"
                Content="Загрузить" Command="{Binding OpenFilesCommand}"/>
    </Grid>
Всё работает как и задумывалось.
Загружаются только те изображения которые нужны на экране.
Выгружаются не сразу, а после пролистывания на экран или чуть больше.

Причем выгрузка - это не значит освобождения памяти!
Освободится она только если это затребует система.

А так если возвращается скрулл назад к уже выгруженным элементам, то если они ещё в памяти, то просто возвращается ссылка на них.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.01.2020, 16:23

Свойства и методы элементов управления для пользовательской формы.
Помогите, пожалуйста, составить программу, выводящую на экран пользовательскую форму, на которой расположены поле со списком, содержащее...

Класс, содержащий методы для нахождения кол-ва не нулевых элементов
Разработать собственный класс, содержащий методы для нахождения кол-ва не нулевых элементов и вычисления суммы отрицательных элементов...

Создать стек сплошным представлением и продемонстрировать методы класса для стека из 15 элементов
нужно создать стек сплошным представлением и продемонстрировать методы класса для стека из 15ти элементов. Не могу понять как описать...

Разработать собственный класс, содержащий методы для нахождения количества отрицательных элементов массива
Доброе утро !! Помогите пожалуйста Разработать собственный класс, содержащий методы для нахождения количества отрицательных элементов...

Разработать классы для описанных ниже объектов. Включить в класс методы set (…), get (…), show (…). Определить другие методы
Разработать классы для описанных ниже объектов. Включить в класс методы set (…), get (…), show (…). Определить другие методы Abiturient:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru