Tôi đang làm việc trên một công cụ hỗ trợ hiển thị nhiều TabItem
s trong một TabControl
. Mỗi TabItem
đại diện cho một nhân viên và trong mỗi nhân viên này, Tab
có một số khác là TabControl
có chứa thêm TabItem
s. Những TabItem
s đại diện cho các thư mục Outlook cho nhân viên đó (như "Làm việc", "Đã hoàn tất", v.v.). Mỗi thư mục trong số các thư mục TabItem
s này chứa ListBox
được gắn với một số ObservableCollection
của MailItem
s liên quan đến thư mục Outlook đó. Đây không phải là những bộ sưu tập khổng lồ - chỉ có một tá hoặc nhiều mặt hàng trên mỗi ListBox
. Mặc dù, tổng cộng, trên tất cả các TabItem
s có thể hình dung được 100 mục hoặc hơn.Bí quyết tạo giao diện người dùng WPF đáp ứng khi điền nhiều ListBox là gì?
Cách tôi hiện đang xây dựng ứng dụng là ứng dụng sẽ kích hoạt và điền vào màn hình với các tab và tab phụ của nhân viên thích hợp. Quá trình này khá nhanh và tôi rất vui. Tôi đã tạo ra một Static Global.System.Timer
rằng tất cả thư mục của mã sau TabItem
được đồng bộ với. Vì vậy, cứ sau 5 phút ứng dụng sẽ xóa tất cả ObserverableCollection
và quét lại các thư mục Outlook.
Vấn đề là quá trình quét sẽ khiến ứng dụng ngừng hoạt động. Tôi đã cố gắng sử dụng một BackgroundWorker
để thu thập email từ Outlook như một quá trình nền, sau đó vượt qua một đối tượng List<MailItem>
đến một phương pháp RunWorkerCompleted
rằng sau đó chạy một quá trình this.Dispatcher.BeginInvoke
mà xóa tương ứng ObservableCollection
sau đó thêm các mục từ List<MailItem>
trở lại ObservableCollection
. Tôi thậm chí đã đặt số này Dispatcher
thành mức độ ưu tiên thấp hơn.
Mặc dù vậy, ứng dụng là cảm giác rất clunky trong quá trình quét/điền. Tôi không rõ ràng về cách thiết kế tốt hơn điều này và tôi thừa nhận tôi có phần mới với điều này. Tôi nhận ra rằng việc xóa từng số ObservableCollection
s không hiệu quả, nhưng các sự kiện thay đổi thư mục Outlook không đáng tin cậy, vì vậy tôi cần quét lại một lần để đảm bảo tất cả các số MailItem
được biểu diễn.
Dưới đây là mã của tôi cho điều khiển WPF có chứa ListBox
. Hãy nhớ rằng có khoảng 10 trong số các điều khiển ListBox
này hoạt động cùng một lúc.
// This entire UserControl is essentially a ListBox control
public partial class TicketListView : UserControl
{
private TicketList _ticketList; //this is the ObservableCollection object
private Folder _folder; // Outlook Folder
public TicketListView(Folder folder)
{
InitializeComponent();
_ticketList = this.FindResource("TicketList") as TicketList;
_folder = folder;
GlobalStatics.Timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Refresh();
}
private void Refresh()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
List<MailItem> tickets = new List<MailItem>();
string filter = TicketMonitorStatics.TicketFilter(14);
Items items = _folder.Items.Restrict(filter);
try
{
foreach (MailItem mi in items.OfType<MailItem>())
{
tickets.Add(mi);
}
}
catch (System.Exception) { }
e.Result = tickets;
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
List<MailItem> tickets = e.Result as List<MailItem>;
this.Dispatcher.BeginInvoke(new System.Action(delegate
{
_ticketList.Clear();
PopulateList(tickets);
}));
BackgroundWorker worker = sender as BackgroundWorker;
worker.Dispose();
}
private void PopulateList(List<MailItem> ticketList)
{
foreach (MailItem mi in ticketList)
{
this.Dispatcher.BeginInvoke(new System.Action(delegate
{
_ticketList.Add(mi);
}), System.Windows.Threading.DispatcherPriority.SystemIdle);
}
}
}
Có vẻ một chút lẻ bạn đang gặp như vậy vấn đề hiệu suất lớn với dữ liệu nhỏ như vậy, tôi có một ứng dụng tương tự, Tabbed triển vọng mailreader bao gồm các thư mục với tối đa 5000 mặt hàng và điều này không treo UI , Loại 'Timer' là' GlobalStatics.Timer', tôi sử dụng 'Threading.Timer' để loại bỏ nhu cầu của' BackgroundWorker', Có hình ảnh nào liên kết với các mục thư này không? –
Trình xử lý RunWorkerCompleted có chạy trên luồng mà BackgroundWorker đã được tạo không? Nếu đó là trường hợp bạn không cần sử dụng Bộ điều phối để chạy mã trên chuỗi giao diện người dùng vì bạn đã ở trên chuỗi giao diện người dùng. – Andy