Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
Я новичек, не стукайте
7 / 7 / 3
Регистрация: 05.05.2022
Сообщений: 274
1
.NET 7

ListBox как отключить автоматическую прокрутку вверх при добавлении в него элементов?

04.09.2023, 13:35. Показов 686. Ответов 12
Метки wpf (Все метки)

Author24 — интернет-сервис помощи студентам
Есть листбокс в чате, в нем сообщения подгружаются по мере прокрутки вверх, но при добавлении новых элементов в листбокс, он автоматически пролистывается вверх, можно ли это как-то убрать?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.09.2023, 13:35
Ответы с готовыми решениями:

QListView запретить автоматическую прокрутку скроллбара при добавлении новых элементов
Собственно, вопрос в теме. Как заставить QListView не прокручиваться за вновь добавляемыми...

Как отключить автоматическую прокрутку?
Доброго времени суток! проблема следующая посадил за комп малыша поставил мультик и отлучился)) в...

Как сделать автоматическую прокрутку страницы при открытии
Что и куда надо прописать, чтобы при открытии определенных страниц на сайте шло автоматическое...

Как сделать автоматическую сортировку по дате при добавлении строк?
Есть форма, требуется чтобы при добавлении строки с новой датой она автоматически сортировалась по...

12
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
04.09.2023, 16:36 2
Budka3000, как добавляете?
0
Я новичек, не стукайте
7 / 7 / 3
Регистрация: 05.05.2022
Сообщений: 274
05.09.2023, 11:29  [ТС] 3
Цитата Сообщение от Элд Хасп Посмотреть сообщение
как добавляете?
Просто в коллекцию добавляем
0
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
05.09.2023, 13:40 4
Цитата Сообщение от Budka3000 Посмотреть сообщение
Просто в коллекцию добавляем
Свойство "только для чтения" типа ObservableCollection и добавляете методом Add?
0
Я новичек, не стукайте
7 / 7 / 3
Регистрация: 05.05.2022
Сообщений: 274
05.09.2023, 14:17  [ТС] 5
Цитата Сообщение от Элд Хасп Посмотреть сообщение
методом Add?
через Insert
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Свойство "только для чтения"
не понял
0
2840 / 1960 / 366
Регистрация: 14.08.2018
Сообщений: 6,334
Записей в блоге: 4
05.09.2023, 14:36 6
Цитата Сообщение от Budka3000 Посмотреть сообщение
не понял
C#
1
2
3
4
5
public ObservableCollection<MyType> MyCollection { get; } = new ObservableCollection<MyType>();
 
// .....
 
MyCollection.Add(MyTypeObject);
1
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
05.09.2023, 22:33 7
Цитата Сообщение от Budka3000 Посмотреть сообщение
через Insert
Проверю вечером.
Вообще не сталкивался с тем чтобы это создавало проблемы, но может просто не обращал внимания.

Цитата Сообщение от Budka3000 Посмотреть сообщение
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Свойство "только для чтения"
не понял
Если сменяется коллекция, то будет происходить сброс скрулла.
Покажите как у вас реализовано свойство.

Добавлено через 4 часа 25 минут
Цитата Сообщение от Budka3000 Посмотреть сообщение
но при добавлении новых элементов в листбокс, он автоматически пролистывается вверх, можно ли это как-то убрать?
Поставил эксперимент.
Не скрулл пролистывается вверх. Область видимости остаётся на месте. Но если добавлять элементы в области видимости ил на ней, то список расширяется на это количество элементов. А так как видимая часть остаётся на месте (условно по индексу показываемых элементов), то список видимых элементов смещается вниз.

У вас так же? Вы именно об этом писали?

Добавлено через 2 минуты
Здесь получается довольно сложная логика. Если добавляется элемент по индексу меньше верхнего в видимой области, то надо видимую область смещать на количество добавленных элементов. Тогда визуально элементы в видимой области будут стоять на месте.
0
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
05.09.2023, 23:46 8
Лучший ответ Сообщение было отмечено Budka3000 как решение

Решение

Budka3000, Пример реализации.

Добавлено через 1 минуту
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
    public static class VisualTreeHelper
    {
        public static IEnumerable<DependencyObject> GetChildren(this DependencyObject reference)
        {
            ArgumentNullException.ThrowIfNull(reference);
            Queue<DependencyObject> queue = new Queue<DependencyObject>(16);
            queue.Enqueue(reference);
            while (queue.Count != 0)
            {
                DependencyObject current = queue.Dequeue();
                int count = GetChildrenCount(current);
                for (int i = 0; i < count; i++)
                {
                    queue.Enqueue(GetChild(current, i));
                }
                yield return current;
            }
        }
        public static IEnumerable<T> GetChildren<T>(this DependencyObject reference)
           where T : DependencyObject
            => reference.GetChildren().OfType<T>();
 
        public static T FindAncestor<T>(this DependencyObject dobj)
            where T : DependencyObject
        {
            while (dobj is not null)
            {
                if (dobj is T t)
                    return t;
 
                dobj = GetParent(dobj);
            }
            return null;
        }
 
        public static FrameworkElement FindDataAncestor<TData>(this DependencyObject dobj)
        {
            while (dobj is not null)
            {
                if (dobj is FrameworkElement element and { DataContext: TData })
                    return element;
 
                dobj = GetParent(dobj);
            }
            return null;
        }
 
        public static TData FindData<TData>(this DependencyObject dobj)
        {
            FrameworkElement element = dobj.FindDataAncestor<TData>();
            if (element == null)
                return default;
            return (TData)element.DataContext;
        }
 
    }
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Window x:Class="Core2023.Topics.Budka3000.ScrollTop.NumsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Core2023.Topics.Budka3000.ScrollTop"
        mc:Ignorable="d"
        Title="NumsWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:NumsVM/>
    </Window.DataContext>
    <Grid>
        <ListBox x:Name="lBox" ItemsSource="{Binding Nums}" LayoutUpdated="OnLayoutUpdate" />
    </Grid>
</Window>
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
    public partial class NumsWindow : Window
    {
        public NumsWindow()
        {
            InitializeComponent();
            NumsVM vm = (NumsVM)DataContext;
            BindingOperations.EnableCollectionSynchronization(vm.Nums, ((ICollection)vm.Nums).SyncRoot);
            ((INotifyCollectionChanged)vm.Nums).CollectionChanged += OnNumsChanged;
            Loaded += async delegate
            {
                await vm.Start();
            };
        }
 
        private void OnNumsChanged(object? sender, NotifyCollectionChangedEventArgs e)
        {
            scroll?.Dispatcher.Invoke(() =>
            {
                double offset = scroll.ContentVerticalOffset;
                double offs = 0;
                if (e.NewStartingIndex <= offset)
                {
                    offs += e.NewItems?.Count ?? 0;
                }
                if (e.OldStartingIndex <= offset)
                {
                    offs -= e.OldItems?.Count ?? 0;
                }
                if (offs != 0)
                {
                    scroll.ScrollToVerticalOffset(offset + offs);
                }
                Debug.WriteLine(offset);
            });
        }
 
        private ScrollViewer? scroll = null;
 
        private void OnLayoutUpdate(object sender, EventArgs e)
        {
            scroll = lBox.GetChildren<ScrollViewer>().FirstOrDefault();
        }
    }
Добавлено через 2 минуты
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    public class NumsVM
    {
        public ReadOnlyObservableCollection<int> Nums { get; }
        private readonly ObservableCollection<int> ints;
 
        public NumsVM() => Nums = new(ints = new(Enumerable.Range(0,100).Reverse()));
 
        public async Task Start() => await Task.Run(async () =>
        {
            while (true)
            {
                ints.Insert(0, ints.Count);
                await Task.Delay(1000);
            }
        });
    }
1
Я новичек, не стукайте
7 / 7 / 3
Регистрация: 05.05.2022
Сообщений: 274
08.09.2023, 13:15  [ТС] 9
Спасибо, но это работает только если фиксированный размер контейнера листбокса, а как сделать учитывая автоматический размер?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
private void OnNumsChanged(object? sender, NotifyCollectionChangedEventArgs e)
0
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
08.09.2023, 19:32 10
Цитата Сообщение от Budka3000 Посмотреть сообщение
а как сделать учитывая автоматический размер?
Сходу не смогу сказать.
По идее в дефолтном режиме ScrollViewer осуществляет смещение по количеству элементов. И это не должно зависеть от их размера.
Размер будет влиять если смещение задаётся в пикселях.

Будет время - проверю.

Добавлено через 3 часа 43 минуты
Budka3000, проверил с такой VM:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public class NumsVM
    {
        public ReadOnlyObservableCollection<string> Nums { get; }
        private readonly ObservableCollection<string> ints;
 
        public NumsVM() => Nums = new(ints = new(Enumerable.Range(0, 100).Reverse().Select(i => i.ToString())));
 
        private static readonly Random random = new Random();
        public async Task Start() => await Task.Run(async () =>
        {
            while (true)
            {
                ints.Insert(0, string.Join(Environment.NewLine, Enumerable.Range(0, random.Next(5)).Select(i => "\t" + i).Append(ints.Count.ToString())));
                await Task.Delay(1000);
            }
        });
    }
Всё работает нормально.

Добавлено через 45 секунд
Держит область видимости, даже если она начинается не с полного элемента.
0
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
08.09.2023, 22:49 11
Budka3000, с разными типами элементов и шаблонами для них тоже проверил. Всё работает нормально.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public class NumsVM
    {
        public ReadOnlyObservableCollection<object> Nums { get; }
        private readonly ObservableCollection<object> ints;
 
        public NumsVM() => Nums = new(ints = new(Enumerable.Range(0, 100).Reverse().Select(i => (object)i)));
 
        private static readonly Random random = new Random();
        public async Task Start() => await Task.Run(async () =>
        {
            while (true)
            {
                ints.Insert(0, random.Next(2) == 0 ? ints.Count : ints.Count.ToString());
                await Task.Delay(1000);
            }
        });
    }
XML
12
13
14
15
16
17
18
19
20
21
22
23
    <Grid xmlns:sys="clr-namespace:System;assembly=mscorlib">
        <ListBox x:Name="lBox" ItemsSource="{Binding Nums}" LayoutUpdated="OnLayoutUpdate">
            <ListBox.Resources>
                <DataTemplate DataType="{x:Type sys:Int32}">
                    <TextBlock Text="{Binding}" Background="Aqua" Padding="5"/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type sys:String}">
                    <TextBlock Text="{Binding}" Background="AliceBlue" Padding="10" FontSize="20"/>
                </DataTemplate>
            </ListBox.Resources>
        </ListBox>
    </Grid>
1
Я новичек, не стукайте
7 / 7 / 3
Регистрация: 05.05.2022
Сообщений: 274
12.09.2023, 11:35  [ТС] 12
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Размер будет влиять если смещение задаётся в пикселях.
Хотел еще спросить, был параметр VirtualizingPanel.ScrollUnit="Pixel" благодаря которому, была плавный скролл, но, с ним не корректно работало, можно ли как-то сделать что бы оставался этот параметр?
0
Модератор
Эксперт .NET
15790 / 10947 / 2843
Регистрация: 21.04.2018
Сообщений: 32,123
Записей в блоге: 2
12.09.2023, 13:15 13
Цитата Сообщение от Budka3000 Посмотреть сообщение
но, с ним не корректно работало, можно ли как-то сделать что бы оставался этот параметр?
Что-то сильно сложное должно быть...
Чтобы в области визуализации оставались одни и те же элементы коллекции, нужно смещать область на количество добавляемы-удаляемых элементов. То есть нужно смещение в элементах, а не в пикселях.
Возможно получится переключить в Item, сместить на нужное количество элементов и потом вернуть Pixel. Но это нужно проверять.
0
12.09.2023, 13:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.09.2023, 13:15
Помогаю со студенческими работами здесь

Как сделать при добавлении нового материала - автоматическую ссылку на другой странице
Сложный вопрос, но реально ли это как-нибудь сделать? Пробую использовать разные CMS сейчас. На...

Как сделать автоматическую генерацию страниц при добавлении определенного количества записей Wordpress?
Занимаясь посадкой шаблона на Wordpress столкнулся еще с одной проблемой.. Есть страница, на нее...

Как становить автоматическую прокрутку элемента?
Вот с помощью этого кода автоматически обновляю содержимое блока div: function show() { ...

Как сделать автоматическую прокрутку текста?
Как сделать чтобы ответ из массива 3 секунды повисел и начинал пролистываться(там будет десяток...

Как добавить автоматическую прокрутку слайдера
Здравствуйте ! Как сделать так чтобы слайдер сам перелистывался, не меняя самого слайдера....

Как сделать автоматическую прокрутку текста?
Привет, я недавно в Unity и хотел бы узнать, как сделать автоматическую прокрутку текста с права на...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru