2009-05-26 8 views
0

Ich habe eine Listbox in XAML definiert als:WPF Listbox Nachziehen nicht

<ListBox x:Name="directoryList" 
       MinHeight="100" 
       Grid.Row="0" 
       ItemsSource="{Binding Path=SelectedDirectories}"/> 

Die SelectedDirectories ist eine Eigenschaft, auf die Listen Datacontext vom Typ List<DirectoryInfo>

Die Klasse, die die Datacontext für die Listbox ist implementiert INotifyPropertyChanged . Wenn sich die Auflistung ändert, werden die Elemente erfolgreich zur Liste hinzugefügt, die Anzeige wird jedoch nicht aktualisiert, bis ich die Listbox erzwinge, die Größe neu zu bestimmen.

Irgendwelche Ideen warum?

EDIT: INotifyPropertyChanged Umsetzung

public class FileScannerPresenter : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     private FileScanner _FileScanner; 

     public FileScannerPresenter() 
     { 
      this._FileScanner = new FileScanner(); 
     } 

     public List<DirectoryInfo> SelectedDirectories 
     { 
      get 
      { 
       return _FileScanner.Directories; 
      } 
     } 

     public void AddDirectory(string path) 
     { 
      this._FileScanner.AddDirectory(path); 
      OnPropertyChanged("SelectedDirectories"); 
     } 

     public void OnPropertyChanged(string property) 
     { 
      if (this.PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(property)); 
      } 
     } 
    } 

Antwort

3

Versuchen

ObservableCollection<DirectoryInfo> 

statt - du bist ohne Grund eine Aktualisierung des gesamten ListBox Triggerung und Sie müssen nicht Ihr Hosting-Klasse machen implementieren Sie INotifyPropertyChanged - es könnte einfach eine Eigenschaft des Fensters sein. Der Schlüssel besteht darin, die Eigenschaft nie auf eine neue Instanz zu setzen. Also:

class SomeWindow : Window { 
    public ObservableCollection<DirectoryInfo> SelectedDirectories {get; private set;} 

    SomeWindow() { SelectedDirectories = new ObservableCollection<DirectoryInfo>(); } 

    public void AddDirectory(string path) { 
     SelectedDirectories.Add(new DirectoryInfo(path)); 
    } 
} 

Wenn Sie die Filescanner-Klasse am Ende, müssen Sie INotifyCollectionChanged stattdessen implementieren - so weiß die List-Box, was dynamisch hinzufügen/entfernen.

+0

Du hast Recht w.r.t. warum mein vorheriger Codeausschnitt funktioniert hat. Aktualisiert. +1 – Gishu

+0

Was ich am Ende getan habe, war die Sammlung in einer Presenter-Klasse in einer ObservableCollection zu abstrahieren und dann nur bei Bedarf an die Scanner-Klasse zu übergeben. – benPearce

0

(Siehe Update unten). WPF scheint gut zu funktionieren. Ich habe deinen Code in ein neues Projekt eingefügt. Das Listenfeld wird aktualisiert, wenn ich auf die Schaltfläche klicke, um AddDirectory aufzurufen. Sie sollten keine Codeänderungen mehr benötigen. Das Problem scheint etwas anderes zu sein .. Gibt es mehrere Threads in Ihrer Benutzeroberfläche?

Ich hatte nicht den FileScanner-Typ. Also habe ich einen Dummy wie folgt erstellt.

public class FileScanner 
    { 
     string _path; 
     public FileScanner() 
     {  _path = @"c:\";  } 
     public List<DirectoryInfo> Directories 
     { 
     get 
     { 
      return Directory.GetDirectories(_path).Select(path => new DirectoryInfo(path)).ToList(); 
     } 
     } 

     internal void AddDirectory(string path) 
     {   _path = path;  } 
    } 

Keine Änderungen an der FileScannerPresenter-Klasse. Oder Ihre Listbox XAML. Ich habe ein Fenster mit einem DockPanel erstellt, das Ihre Listbox, ein Textfeld und eine Schaltfläche enthält.

Update: Paul Betts hat Recht. Es funktioniert, weil ich jedes Mal eine neue Liste von der gebundenen Eigenschaft zurückgebe. Datenbindung mit Listen bringt mich immer durcheinander. Mit mehr Bastelei, die einfache Möglichkeit, dies zu tun ist:

  • Make Filescanner # Verzeichnisse eine ObservableCollection<DirectoryInfo> zurückkehren (die INotifyCollectionChanged für Sie implementiert). Ändern Sie alle Signaturen ganz nach oben, um diesen Typ anstelle eines List<DirectoryInfo>
  • FileScanner und FileScannerPresenter selbst müssen keine INotifyXXX-Schnittstelle implementieren.

    // in FileScanner class def   
        public ObservableCollection<DirectoryInfo> Directories 
        { 
        get 
        { return _DirList; } 
        } 
        internal void AddDirectory(string path) 
        { 
        _path = path; 
        //var newItems = Directory.GetDirectories(_path).Select(thePath => new DirectoryInfo(thePath)).ToList(); 
        //_DirList.Concat(newItems); -- doesn't work for some reason. 
        foreach (var info in Directory.GetDirectories(_path).Select(thePath => new DirectoryInfo(thePath)).ToList()) 
        { 
         _DirList.Add(info); 
        } 
        } 
    
+1

Ihr Code funktioniert, weil der Getter der Liste <> jedes Mal eine neue Liste zurückgibt - wenn er dieselbe Liste zurückliefert (d. H. Eine Liste, die in der .ctor von FileScanner instanziiert wird, würde dies nicht funktionieren) –