2011-08-21 23 views
5

Tôi đang phát triển một ứng dụng mã nguồn mở có tên là Media Assistant. Tôi đã sử dụng một ListBox để hiển thị thư viện. ItemsSource bị ràng buộc vào một danh sách của LibraryItem. Đây là XALM.Hộp danh sách WPF cuộn lên trên cùng khi tôi thay đổi thông báo trạng thái hoặc hiển thị màn hình chờ

<ListBox Name="Tree" DockPanel.Dock="Top" 
    ItemsSource="{Binding DataSource.OrderedLibraryItems}" 
    Background="{StaticResource LibraryBackground}" 
    Width="220" HorizontalAlignment="Left" 
    BorderThickness="0" 
    VirtualizingStackPanel.IsVirtualizing="True" 
    VirtualizingStackPanel.VirtualizationMode="Standard" 
    ScrollViewer.IsDeferredScrollingEnabled="True" 
    ItemTemplate="{StaticResource ListLibraryItemTemplate}" 
    SelectionMode="Single" 
    MouseDoubleClick="HandleMouseDoubleClick" 
/> 

Vấn đề là khi tôi hiển thị bất kỳ thông báo trạng thái nào ở cuối cửa sổ của mình từ chuỗi bằng cách sử dụng Bộ điều phối.

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,new ParameterizedThreadStart(action), state); 

Hộp danh sách cuộn lên trên cùng. Nếu tôi không hiển thị bất kỳ thông điệp trạng thái nào thì nó hoạt động tốt. Văn bản dữ liệu hoặc các mục danh sách hoặc tiêu điểm không bị thay đổi. Tôi không thể tìm thấy bất kỳ lý do gì tại sao nó lại làm điều đó. Nó xảy ra khi tôi hiển thị bất kỳ màn hình chờ đợi nào là một cửa sổ không theo phương thức. Tôi không thể tái tạo nó trong một dự án khác. Here là mã nguồn của Trợ lý phương tiện. Bạn có thể dễ dàng tạo lại nó bằng cách bỏ chú thích câu lệnh trả về của phương thức SetStatusMessage tại lớp BackgroundScanner.

+0

Tôi có một cái gì đó tương tự và tất cả tôi có thể hình dung là giao diện người dùng muốn chọn mục theo quan điểm. Nếu chỉ số là -1 thì nó đã cố gắng hiển thị 0. Tôi đã không sử dụng một thông điệp Dispatcher nhưng nếu tôi đặt TextBlock trên ListBox tôi đã có may mắn hơn nhưng không bao giờ có nó làm việc tất cả các cách. Với một ListView tôi có hành vi tốt hơn. ListBox là nhanh và tôi sill như nó nhưng là một số công cụ tôi đã không tìm ra. Nếu không có cuộn trả chậm, bạn có nhận được cùng một hành vi không? Nếu chế độ ràng buộc của bạn là oneway thì hãy khai báo nó. – Paparazzi

Trả lời

3

Tôi đã tìm ra lý do đằng sau điều này, vì vậy giải pháp. Tôi đã sử dụng DockPanel để bố cục giao diện người dùng của mình. Tôi đặt thanh trạng thái của tôi ở phía dưới, ListBox bên trái và các mục khác nằm ở giữa và trên. Có một TextBlock trong StatusBar của tôi có chiều rộng và Height được đặt thành Auto. Vì vậy, khi tôi thay đổi văn bản của TextBlock StatusBar của tôi nó chiều rộng và chiều cao được tính toán lại và nó của cha mẹ tính toán lại nó bố trí. Do đó ListBox được gọi đến các phép đo và sắp xếp. Mặc dù kích thước của nó không bị thay đổi, nó sẽ đặt lại vị trí cuộn lên trên cùng. Nó xảy ra chỉ khi tôi sử dụng ScrollViewer.CanContentScroll = "True" tại ListBox. Theo mặc định, nó là True. Vì vậy, mặc dù tôi đã không đặt giá trị này Nó đã được đặt lại vị trí di chuyển. Nếu tôi vô hiệu hóa nó bằng cách sử dụng ScrollViewer.CanContentScroll = "False" thì nó hoạt động tốt.

<ListBox Name="Tree" DockPanel.Dock="Top" 
    ItemsSource="{Binding DataSource.OrderedLibraryItems}" 
    Background="{StaticResource LibraryBackground}" 
    Width="220" HorizontalAlignment="Left" 
    BorderThickness="0" 
    VirtualizingStackPanel.IsVirtualizing="True" 
    VirtualizingStackPanel.VirtualizationMode="Standard" 
    ScrollViewer.IsDeferredScrollingEnabled="True" 
    ScrollViewer.CanContentScroll="False" 
    ItemTemplate="{StaticResource ListLibraryItemTemplate}" 
    SelectionMode="Single" 
    MouseDoubleClick="HandleMouseDoubleClick" 
/> 

Nhưng thiết ScrollViewer.CanContentScroll = "False" vô hiệu hóa ảo hóa và tôi muốn sử dụng ảo hóa để ListBox của tôi vì vậy tôi thiết lập cố định Chiều cao và rộng để TextBlock. Vì vậy, DockPanel không sắp xếp lại con của nó nếu tôi thay đổi thông điệp trạng thái.

Có thể đó là lỗi tại ScrollViewer. Nó không nên thay đổi vị trí cuộn nếu kích thước không thay đổi.

+0

Câu trả lời của bạn là giải pháp thay thế. Nó có nghĩa là không có giải thích đã được chứng minh và giải pháp này có thể không phù hợp cho tất cả mọi người. Bạn có thể bỏ chọn cờ "câu trả lời giải quyết câu hỏi" để mọi người vẫn có thể đăng một giải pháp thực sự không? Tôi đã gặp vấn đề tương tự và không thể sửa các thứ nguyên cho ứng dụng của mình. – SandRock

+0

Nếu "giải pháp" hoạt động cho người đăng, họ nên kiểm tra. Người dùng khác có thể muốn cung cấp tốt hơn (tức là "sửa chữa thực sự" trong trường hợp này) câu trả lời và upvite giải pháp tốt hơn nhưng đó là cách SO hoạt động tôi nghĩ. Tôi có một trường hợp mà câu trả lời của tôi có 5 upvotes mặc dù câu trả lời "chính xác, kiểm tra" chỉ có một :) Có lẽ tôi sai về cách làm việc này buyt đó là những gì tôi nghĩ. –

+0

Đúng, bạn nói đúng. Tôi đã đăng một khoản tiền thưởng thay thế :) – SandRock

-1

Vì bố cục đang được đặt lại, hộp dự kiến ​​sẽ chọn mục đầu tiên (0).

Bạn có thể cố gắng để thiết lập các mục đã chọn vào số hạng mục hiện có trong hộp danh sách:

Tree.SelectedIndex = Tree.Items.Count; 

Tôi không thử nghiệm giải pháp này trên mã của bạn nhưng tôi đã sử dụng nó trong một dự án của tôi ở đâu Tôi đã có một vấn đề tương tự.

Hy vọng điều đó sẽ hữu ích.

+0

Cảm ơn câu trả lời của bạn. WPF không thực sự chọn mục đầu tiên khi thay đổi kích thước xảy ra: nó chỉ đặt lại scrollviewer Vertical và Horizontal Offsets. Khi sự cố xảy ra, tôi không muốn thay đổi lựa chọn của người dùng nhưng ngăn scrollviewer đặt lại về 0. Tôi xin lỗi nhưng giải pháp của bạn có tác dụng phụ không mong muốn (thay đổi lựa chọn). – SandRock

+0

Sai lầm của tôi, tôi hiểu nó rất tệ. Để ngăn chặn tác dụng phụ, mảng mục đã chọn có thể được lưu trữ và được khôi phục sau khi "làm mới" xảy ra. Dù sao nó không phải là giải pháp cho vấn đề. – Pimenta

0

Hãy thử điều này:

listBox1.ScrollIntoView(listBox1.Items.GetItemAt(listBox1.Items.Count - 1)); 
+0

Mã của bạn làm cho ScrollViewer của ListBox cuộn đến mục cuối cùng. Tôi muốn scrollviewer ở lại vị trí trước đó (có thể từ 0 đến N-1). – SandRock

0

Trong thư trả lời vào câu trả lời @ user904627 của, đây là một phiên bản nâng cao của workaround mình. Vấn đề với chỉ sửa chữa WidthHeight là ListBox giữ cùng một vị trí ngay cả khi người dùng thay đổi kích thước cửa sổ. Không thể chấp nhận được.Đây là lý do tại sao tôi tạo ra hành vi nhỏ bé này sửa chữa Chiều rộng và Chiều cao nhưng lắng nghe sự kiện SizeChanged của thành phần gốc để cho ListBox thay đổi kích thước khi kích thước vùng chứa thay đổi.

Mã này là ở đây: VirtualizedListBoxFixBehavior

Khi yếu tố phụ huynh được thay đổi kích cỡ, tôi khôi phục WidthHeight-double.NaN (vì vậy điều khiển có thể thay đổi kích thước chính nó) và tôi xếp hàng các bit mã mà sửa các thuộc tính kích thước thực tế các giá trị trong Dispatcher để thực thi sau này.

Nhưng đây vẫn là một workaround làm việc xấu xí ...

Các vấn đề liên quan