Tôi có một WPF ListBox
được liên kết với một số ObservableCollection
. Khi mọi thứ được thêm vào bộ sưu tập, vị trí di chuyển ListBox
sẽ thay đổi theo kích thước của các mục được thêm vào. Tôi muốn có thể duy trì vị trí cuộn, để ngay cả khi mọi thứ được thêm vào danh sách, các mục hiện đang xem không di chuyển. Có cách nào để hoàn thành nó không?Bảo quản vị trí cuộn của Hộp danh sách WPF bị ràng buộc khi bộ sưu tập thay đổi
Trả lời
Tôi không chắc chắn nếu có ghi đè cho điều đó, nhưng tôi nghi ngờ điều đó.
Khi nghi ngờ sử dụng tính năng ràng buộc thủ công? : -} Nghiêm túc, hành vi ràng buộc mặc định sẽ là - tốt - mặc định, vì vậy nếu bạn cần ràng buộc thủ công hành vi đặc biệt là một lựa chọn tốt hơn. Với liên kết thủ công, bạn có thể lưu vị trí cuộn và đặt lại vị trí sau khi bạn đã thêm các mục.
Điều này dẫn đến một câu hỏi rõ ràng - làm cách nào để xác định vị trí cuộn hiện tại? –
Tạo bộ sưu tậpXem. Hãy thử cách này:
private ObservableCollection<int> m_Values;
private CollectionView m_View;
private void Bind()
{
m_Values = new ObservableCollection<int>();
m_View = new CollectionView(m_Values);
MyListBox.ItemsSource = m_View;
}
private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine(m_View.CurrentItem);
Debug.WriteLine(m_View.CurrentPosition);
}
Vui lòng giải thích thêm. Câu trả lời này dường như không giải quyết được vấn đề - nó chỉ báo cáo mục và vị trí hiện tại. Tôi đang gặp vấn đề tương tự, bằng cách sử dụng một ListBox với một ItemsPanel đặt thành một VirtualizingStackPanel. Vấn đề như tôi thấy là các mục trong hộp danh sách tiếp tục di chuyển khi các mục mới được thêm vào bộ sưu tập quan sát được. Mặc dù có thể di chuyển các mục trở lại vị trí của chúng sau khi một mục mới được thêm vào (ví dụ: bằng cách sử dụng SelectedIndex), điều này tạo ra một chuyển động giật. Điều cần thiết là một cách để ngăn vị trí cuộn thay đổi ngay từ đầu khi các mục mới được thêm vào. – CyberMonk
Tôi có cùng một vấn đề, nhưng giải pháp của bạn giả định somethig được chọn. Nhưng nếu người dùng không muốn chọn bất cứ điều gì? Chỉ cần di chuyển một nơi nào đó và rời khỏi nó. – EvAlex
Bạn có kiểm soát khi mọi thứ được thêm vào không? Tôi có nghĩa là bạn có một hoặc hai điểm xác định nơi dữ liệu được thay đổi? Nếu vậy, một giải pháp dễ dàng (có lẽ không thanh lịch) sẽ có một biến int cục bộ để giữ ListBox.SelectedIndex hiện tại. Ngay trước khi thay đổi dữ liệu, lưu selectIndex vào biến này và sau khi dữ liệu được thêm vào, thiết lập SelectedIndex của listBox thành giá trị của biến này.
Đầu tiên tìm vị trí hiện tại của ListBox.SelectedIndex và sau đó sử dụng ListBox.ScrollIntoView (/ * Current Index * /). Ngay cả khi các mục mới được thêm vào trong danh sách vị trí hiện tại của bạn và xem sẽ giống nhau.
Tôi phải đối mặt với cùng một vấn đề và một hạn chế khác: người dùng không chọn mục, nhưng chỉ cuộn. Đó là lý do tại sao phương pháp ScrollIntoView()
là vô ích. Đây là giải pháp của tôi.
Trước tiên, tôi tạo ra lớp ScrollPreserver
bắt nguồn từ DependencyObject, với tài sản phụ thuộc kèm theo PreserveScroll
kiểu bool:
public class ScrollPreserver : DependencyObject
{
public static readonly DependencyProperty PreserveScrollProperty =
DependencyProperty.RegisterAttached("PreserveScroll",
typeof(bool),
typeof(ScrollPreserver),
new PropertyMetadata(new PropertyChangedCallback(OnScrollGroupChanged)));
public static bool GetPreserveScroll(DependencyObject invoker)
{
return (bool)invoker.GetValue(PreserveScrollProperty);
}
public static void SetPreserveScroll(DependencyObject invoker, bool value)
{
invoker.SetValue(PreserveScrollProperty, value);
}
...
}
thay đổi tài sản callback giả định tài sản được thiết lập bởi ScrollViewer. Phương thức gọi lại thêm ScrollViewer này vào từ điển riêng và thêm trình xử lý sự kiện ScrollChanged vào nó:
private static Dictionary<ScrollViewer, bool> scrollViewers_States =
new Dictionary<ScrollViewer, bool>();
private static void OnScrollGroupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ScrollViewer scrollViewer = d as ScrollViewer;
if (scrollViewer != null && (bool)e.NewValue == true)
{
if (!scrollViewers_States.ContainsKey(scrollViewer))
{
scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer_ScrollChanged);
scrollViewers_States.Add(scrollViewer, false);
}
}
}
Từ điển này sẽ giữ tham chiếu đến tất cả ScrollViewers trong ứng dụng sử dụng lớp này. Trong trường hợp các mục của tôi được thêm vào đầu bộ sưu tập. Vấn đề là vị trí khung nhìn không thay đổi. Sẽ ổn khi vị trí là 0: yếu tố đầu tiên trong chế độ xem sẽ luôn là mục đầu tiên. Nhưng khi phần tử đầu tiên trong khung nhìn có chỉ mục khác 0 và các mục mới được thêm vào - chỉ mục của phần tử đó tăng lên để nó được cuộn xuống. Vì vậy, giá trị bool cho biết của ScrollViewer dọc bù đắp được không 0. Nếu nó là 0 có không cần phải làm bất cứ điều gì, và nếu nó không phải là 0 nó là cần thiết để duy trì vị thế của mình so với các mục trong khung nhìn:
static void scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (scrollViewers_States[sender as ScrollViewer])
(sender as ScrollViewer).ScrollToVerticalOffset(e.VerticalOffset + e.ExtentHeightChange);
scrollViewers_States[sender as ScrollViewer] = e.VerticalOffset != 0;
}
ExtentHeightChange được sử dụng ở đây để cho biết số lượng các mục được thêm vào. Trong các trường hợp của tôi chỉ được thêm vào đầu bộ sưu tập, vì vậy tất cả những gì tôi cần làm là tăng VerticalOffset của ScrollViewer bằng giá trị này. Và điều cuối cùng: sử dụng. Dưới đây là ví dụ về ListBox:
<Listbox ...>
<ListBox.Resourses>
<Style TargetType="ScrollViewer">
<Setter Property="local:ScrollPreserver.PreserveScroll" Value="True" />
</Style>
</ListBox.Resourses>
</ListBox>
Ta-da!Hoạt động tốt đẹp :)
Không phải bộ nhớ bị rò rỉ do từ điển trong trường tĩnh? – TcKs
DependencyProperties là tất cả tĩnh. Bạn có thể đọc về nó ở đây: http://stackoverflow.com/questions/2989431/why-are-dependency-properties-static – EvAlex
Tôi biết. Nhưng trường "scrollViewers_States" không phải là lối tắt cho thuộc tính phụ thuộc. Nó lưu trữ các trường hợp của ScrollViewer. Bạn có một số mã mà loại bỏ trường hợp cũ từ từ điển? – TcKs
- 1. WPF: Combobox mất chỉ mục đã chọn sau khi bị ràng buộc Thay đổi bộ sưu tập ItemSource
- 2. Bộ sưu tập ràng buộc WPF với chỉ mục
- 3. Hộp danh sách Winforms không cập nhật khi thay đổi dữ liệu bị ràng buộc
- 4. WPF Ràng buộc thay đổi màu tô của hình elip
- 5. Silverlight TabControl bị ràng buộc với ObservableCollection <string> không cập nhật khi bộ sưu tập thay đổi
- 6. vị trí xem danh sách đang được thay đổi khi cuộn trên android
- 7. Hộp danh sách WPF - Bắt UIElement thay vì SelectedItem
- 8. Bộ sưu tập ràng buộc WPF vào ComboBox và chọn một mục
- 9. Hộp danh sách WPF với Hộp danh sách - Giao diện người dùng ảo và cuộn
- 10. WPF Cách thay đổi màu của hộp danh sách đã chọn khi hộp danh sách mất tiêu điểm
- 11. GWT Danh sách biên tập ràng buộc
- 12. WPF và MVVM: Thay đổi chuyển đổi ràng buộc dữ liệu khi chạy
- 13. WPF ComboBox vấn đề hiệu suất bằng cách ràng buộc một bộ sưu tập lớn
- 14. Hộp danh sách, cuộn đồng bộ
- 15. Thay đổi vị trí thanh cuộn
- 16. WPF - Ràng buộc để chọn sửa hộp danh sách giữa các điều khiển của người dùng
- 17. Khi cuộn Chế độ xem danh sách tùy chỉnh, giá trị hộp kiểm thay đổi
- 18. C# Cú pháp sưu tập hộp danh sách C#
- 19. Bộ sưu tập ràng buộc vào DataGridView trong Windows Forms
- 20. WPF Xác thực hộp văn bản không bị ràng buộc
- 21. Danh sách ràng buộc các danh sách trong XAML?
- 22. jquery - giữ cửa sổ thay đổi vị trí cuộn trong khi thêm các mục vào danh sách?
- 23. C#/WPF - Lấy vị trí cuộn ScrollViewer?
- 24. Bộ sưu tập và danh sách
- 25. WPF: Tự động ràng buộc danh sách (một số) thuộc tính của đối tượng
- 26. Hộp danh sách WPF Cuộn để kết thúc tự động
- 27. Thay đổi vị trí chuột khi hộp xem được thêm
- 28. WPF DataGrid - duy trì vị trí cuộn sau khi làm mới
- 29. Non-tuần tự ràng buộc bộ sưu tập
- 30. mô hình MVC/Razor ràng buộc bộ sưu tập khi một phần tử là mất tích
Tôi chỉ thực hiện một dữ liệu wpf thực sự đơn giản với một hộp danh sách và khi tôi thêm các mục mà các mục được xem trong chế độ xem ở chế độ xem ... Bạn đang làm gì khác? – TheCodeMonk
Hãy thử thêm các mục mới vào phần mở rộng của bộ sưu tập. Các mục bạn đang xem bắt đầu di chuyển ra khỏi chế độ xem vì các mục mới được thêm vào. Bạn thêm 1 mục - viewport vẫn ở cùng một vị trí (dựa trên chỉ mục) có nghĩa là 1 mục được nhập vào khung nhìn và 1 mục còn lại. – EvAlex