2013-02-14 11 views
5

TabControl'da birden çok TabItem s görüntüleyen bir destek aracı üzerinde çalışıyorum. Her bir TabItem, bir çalışanı temsil eder ve bu çalışanların her birinin içinde Tab s'nin içinde TabItem s bulunan başka bir TabControl vardır. Bu TabItem s, bu çalışanın ("Çalışma", "Tamamlandı" vb.) Outlook klasörlerini temsil eder. Bu klasörün TabItem s her biri, bu Outlook klasörüne ait ObservableCollectionMailItem s'ye bağlı olan bir ListBox içerir. Bunlar büyük koleksiyonlar değil - sadece ListBox'a göre bir düzine kadar ürün. Toplamda, tüm TabItem lar arasında olmasına rağmen, muhtemelen 100 ürün olabilir.Birden çok Liste Kutusunu doldururken duyarlı bir WPF UI oluşturmanın yolu nedir?

Uygulamayı şu anda oluşturduğum yol, uygulamanın uygun çalışan sekmeleri ve alt sekmelerle ekranın patlaması ve doldurulmasıdır. Bu süreç oldukça hızlı ve mutluyum. Global.System.Timer Statik TabItem 'un tüm kodlarının arka planda senkronize edildiği bir istatistik oluşturdum. Yani her 5 dakikada bir uygulama tüm ObserverableCollection s temizleyecek ve Outlook klasörlerini yeniden tarayın.

Sorun, tarama işleminin uygulamayı durma noktasına getirmesidir. Sonra daha sonra ilgili ObservableCollection temizler geri ObservableCollection için List<MailItem> öğeleri ekleyen this.Dispatcher.BeginInvoke sürecini çalışan bir RunWorkerCompleted yöntemine bir List<MailItem> nesneyi geçmesi, bir arka plan işlemi olarak Outlook'tan posta toplamak için bir BackgroundWorker kullanarak çalıştılar. Bu Dispatcher'u bile daha düşük önceliğe ayarladım. Buna rağmen, uygulama tarama/popülasyon ListBox işlemi sırasında çok rahatsız edici bir duygudur. Buna rağmen; Bunu nasıl daha iyi tasarlayacağımı açık değil ve bunun için biraz yeni olduğumu itiraf ediyorum. Ben her ObservableCollection s temizlemenin, verimsiz olduğunu, ancak Outlook klasör değiştirme olaylarının özellikle güvenilir olmadığını fark ediyorum, bu yüzden tüm MailItem s temsil edilmesini sağlamak için her defasında bir kez kaba bir güç yeniden tarama yapmak gerekir.

Aşağıda, ListBox'u içeren WPF denetimi için kodum var. Bu ListBox kontrolünün yaklaşık 10'unun aynı anda aktif olduğunu unutmayın. İhtiyaçlarınız için

// 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); 
      } 
     } 
    } 
+0

kadar 5000'den öğelerle klasörleri içerir Sekmeli görünüm posta okuyucu böyle az veri olan böyle büyük performans sorunları yaşıyorsanız garip biraz, ben benzer bir uygulama var gibi görünüyor ve bu Arayüzü asmak değil , Ne tür bir 'Timer'' 'GlobalStatics.Timer'',' 'BackgroundWorker'' gereksinimini ortadan kaldıran bir Threading.Timer' kullanırım, Bu posta Öğeleriyle ilişkili görüntüler var mı? –

+0

RunWorkerCompleted işleyicisi, BackgroundWorker'ın oluşturulduğu iş parçacığında çalışmıyor mu? Bu durumda, kullanıcı arabiriminde olduğunuzdan beri UI iş parçacığı üzerinde kod çalıştırmak için bir Dispatcher kullanmanız gerekmemelidir. – Andy

cevap

1

, özellikle WPF, Duyarlı bir görünüm tutmak için zamanlayıcı veya arka plan işçisi kullanarak olmamalıdır. Bunun yerine uygulamanızı MVVM deseniyle tasarlamalısınız. MVVM Model, Görünüm ve Görünüm Modelidir; modelde bir değişiklik varsa, model Görünüm Modelini günceller ve görünüm modeli görünümü günceller. Bu sadece "INotifyPropertyChanged" Arayüzü miras alınarak yapılır. İşte

basit bir örnek

Xaml parçasıdır:

<Window x:Class="SimpleMVVM.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="259" Width="445"> 
    <Grid Margin="0,0,2,-3"> 
     <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="10,33,0,0" VerticalAlignment="Top" Width="75"/> 
     <Label x:Name="label" Content="{Binding Name}" HorizontalAlignment="Left" Margin="103,23,0,0" VerticalAlignment="Top" Width="220" BorderBrush="Black" BorderThickness="1" Height="32" Padding="0"/> 

    </Grid> 
</Window> 

Ve .cs Bölüm

using System.ComponentModel; 
using System.Windows; 

namespace SimpleMVVM 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     private AnimalViewModel _animal= new AnimalViewModel(); 

     public MainWindow() 
     { 
      InitializeComponent(); 

      DataContext = _animal; 
      button.Click += (sender, e) => _animal.Name = "Taylor" ; 
     } 
    } 

    public class AnimalViewModel : AnimalModel 
    { 
     public AnimalViewModel() 
     { 
     }   
    } 

    public class AnimalModel : INotifyPropertyChanged 
    { 
     private string _name; 

     public event PropertyChangedEventHandler PropertyChanged; 

     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       if (_name != value) 
       { 
        _name = value; 
        OnPropertyChanged("Name"); 
       } 
      } 
     } 

     private void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName); 
       PropertyChanged(this, args); 
      } 
     } 
    } 

} 

Hayır, düğme tıklama zamanlayıcısı tarafından tetiklenen güncelleme olduğunu bu modeli hayal görünümü güncelleştirmek için bir özellik değiştirilen etkinliği tetikleyen ilk önce güncellenir.

Bu kalıbı kullanarak kodunuz çok güvenilir olacaktır.

Umarım bu yardımcı olur.

Selamlar Jegan

+0

Ehh. Görüntü modeliniz nerede? Sadece görüş ve modeli görüyorum. –

+0

Kod, işaret ettiğin gibi düzenlenmiş! – Jegan

+0

Kodunuz iyi, ama MVMC diyebilirsiniz emin değilim. VM'yi M –

İlgili konular