2012-03-30 4 views
0

Ich muss die Liste der Downloads aktualisieren, wenn der Fortschritt geändert wurde.So aktualisieren Sie ListView, wenn vorhandene Elemente der gebundenen Liste aktualisiert wurden

XAML:

<ListView ItemsSource="{Binding UiList}" x:Name="MyListView"> 
    <ListView.View> 
    <GridView> 
     <GridViewColumn Header="Title"/> 
     <GridViewColumn Header="Progress"/> 
    </GridView> 
    </ListView.View> 
</ListView> 

Ansichtsmodell, das eine Instanz der Logik-Klasse erstellt und aktualisiert den Inhalt der Listview:

class MainWindowViewModel : ViewModelBase 
{ 
    private readonly Logic _logic; 
    public List<Model> UiList { get; set; }   

    public MainWindowViewModel() 
    { 
     _logic = new Logic(); 
     _logic.Update += LogicUpdate; 
     Start = new RelayCommand(() => 
            { 
             var worker = new BackgroundWorker(); 
             worker.DoWork += (sender, args) => _logic.Start(); 
             worker.RunWorkerAsync(); 
            }); 
    } 

    void LogicUpdate(object sender, EventArgs e) 
    { 
     UiList = _logic.List; 
     RaisePropertyChanged("UiList");    
    } 

    public ICommand Start { get; set; } 
} 

Logic:

public class Logic 
{ 
    readonly List<Model> _list = new List<Model>(); 
    public event EventHandler Update; 

    public List<Model> List 
    { 
     get { return _list; } 
    } 

    public void Start() 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      _list.Clear(); 
      _list.Add(new Model{Progress = i, Title = "title1"}); 
      _list.Add(new Model { Progress = i, Title = "title2" }); 

      var time = DateTime.Now.AddSeconds(2); 
      while (time > DateTime.Now) 
      { } 

      Update(this, EventArgs.Empty); 
     } 
    } 
} 

Der obige Code würde nicht aktualisieren Benutzeroberfläche. Ich kenne zwei Art und Weise, wie dieses Problem zu beheben:

  1. in XAML Code-Behind-Aufruf: Application.Current.Dispatcher.Invoke(new Action(() => MyListView.Items.Refresh()));

  2. In Ansichtsmodell ändern List<>-ICollectionView und verwenden Application.Current.Dispatcher.Invoke(new Action(() => UiList.Refresh()));, nachdem die Liste aktualisiert wurde.

Beide Wege führen das Problem: das Listview blinkt und Popup, die immer auf die Nachfrage der Nutzer offen sein sollte schließt nach jedem "refresh":

Popup

<Popup Name="Menu" StaysOpen="False"> 

Ich kann das Popup durch ein anderes Steuerelement oder Panel ersetzen, aber ich brauche seine Möglichkeit, außerhalb des Hauptfensters zu sein (wie auf dem Bildschirm). Aber ich glaube, dass WPF eine andere Möglichkeit bietet, den Inhalt von ListView zu aktualisieren (ohne zu blinken).

PS: Sorry für die lange Frage, aber ich weiß nicht, wie es kurz zu beschreiben ...

+0

Sie sollten die Liste in ObservableCollection ändern. – Silvermind

Antwort

0

Ich habe die Antwort hier: How do I update an existing element of an ObservableCollection?

ObservableCollection ist eine Teillösung. ObservableCollection erhöht das CollectionChanged-Ereignis nur, wenn sich die Sammlung ändert (hinzugefügte, entfernte Elemente usw.) Um Aktualisierungen vorhandener Elemente zu unterstützen, muss jedes Objekt in der Auflistung (in meinem Fall die Model-Klasse) die INotifyPropertyChanged-Schnittstelle implementieren.

// I used this parent (ViewModelBase) for quick testing because it implements INotifyPropertyChanged 
public class Model : ViewModelBase 
{ 
    private int _progress; 
    public int Progress 
    { 
     get { return _progress; } 
     set 
     { 
      _progress = value; 
      RaisePropertyChanged("Progress"); 
     } 
    } 

    public string Title { get; set; } 
} 
1

ich der Grund denken diese Linie nicht funktioniert:

RaisePropertyChanged("UiList"); 

Ist weil Sie die Liste nicht wirklich geändert haben. Sie haben es gelöscht und neu gefüllt, aber es ist immer noch der Verweis auf die gleiche Liste. Es würde mich interessieren zu sehen, was passiert, wenn Sie, anstatt Ihre Liste zu löschen und neu zu füllen, tatsächlich eine neue Liste erstellt haben. Ich denke, dass Ihr ListView wie erwartet aktualisieren sollte. Ob es sich auf Ihr Popup auswirkt oder nicht, weiß ich nicht.

+0

Ja, das Erstellen einer neuen Liste gibt mir einen neuen Weg (beste BTW, Danke!), Um Listview Update zu beheben. Aber es löst Popup-Problem nicht ... –

Verwandte Themen