2017-07-24 1 views
0

Wir haben leider nur zu laden, haben einen Itemscontrol Setup wie dieseMit WPF Items Virtualization Daten für sichtbare Elemente

<ScrollViewer> 
    <ItemsControl ItemsSource="{Binding Items}" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" > 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Data}"></TextBlock> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ScrollViewer> 

mit dem MainViewModel Wesen:

public class MainViewModel : ViewModelBase 
{ 
    public ObservableCollection<AutoUpdatingItem> Items 
    { 
     get; 
     set; 
    } 

    public MainViewModel() 
    { 
     Items = new ObservableCollection<AutoUpdatingItem>(); 
     for (int i = 0; i < 1000; i++) 
     { 
      Items.Add(new AutoUpdatingItem(i)); 
     } 
    } 
} 

und das Ansichtsmodell der Reihe

public class AutoUpdatingItem : ViewModelBase 
{ 
    private readonly DispatcherTimer timer; 

    private int data; 
    public int Data 
    { 
     get { return data; } 
     set { Set(ref data, value); } 
    } 

    public AutoUpdatingItem(int i) 
    { 
     Data = i; 
     timer = new DispatcherTimer(); 
     timer.Interval = TimeSpan.FromMilliseconds(20); 
     timer.Start(); 
     timer.Tick += Timer_Tick; 
    } 

    private void Timer_Tick(object sender, EventArgs e) 
    { 
     // Data would be fetched from WebService here 
     Data++; 
    } 
} 

Wie können wir erreichen, dass nur die sichtbaren Elemente aktualisiert werden? Gibt es eine Möglichkeit, benachrichtigt zu werden, wenn ein Artikel im virtualisierten Panel recycelt wird?

+0

Ich würde Eigenschaft 'IsVisibly' binden und auf der Grundlage dieses Start/Timer stoppen, wenn es notwendig ist . –

Antwort

0

Diese funktionieren kann (siehe: In WPF, how can I determine whether a control is visible to the user?):

public class AutoUpdatingItem : INotifyPropertyChanged 
{ 
    private readonly DispatcherTimer timer; 

    private int data; 
    public int Data 
    { 
     get { return data; } 
     set 
     { 
      data = value; 
      propertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Data))); 
     } 
    } 

    public AutoUpdatingItem() 
    { 
     timer = new DispatcherTimer(new TimeSpan(0,0,0,0,200), DispatcherPriority.Background, Tick, Dispatcher.CurrentDispatcher); 
     timer.Stop(); 
    } 

    private void Tick(object sender, EventArgs e) 
    { 
     Data++; 
    } 

    private event PropertyChangedEventHandler propertyChanged; 
    public event PropertyChangedEventHandler PropertyChanged 
    { 
     add 
     { 
      propertyChanged += value; 
      timer.Start(); 
     } 
     remove 
     { 
      timer.Stop(); 
      propertyChanged -= value; 
     } 
    } 
} 

Mit folgendem XAML:

<ItemsControl ItemsSource="{Binding Items}" 
        VirtualizingStackPanel.IsVirtualizing="True" 
        VirtualizingStackPanel.VirtualizationMode="Recycling" Height="500"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Data}" /> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <VirtualizingStackPanel /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.Template> 
      <ControlTemplate> 
       <Border > 
        <ScrollViewer VerticalScrollBarVisibility="Visible" 
            CanContentScroll="True"> 
         <ItemsPresenter /> 
        </ScrollViewer> 
       </Border> 
      </ControlTemplate> 
     </ItemsControl.Template> 
    </ItemsControl>