WPF ListBox não redesenhar
Pergunta
Eu tenho uma caixa de listagem definido em XAML como:
<ListBox x:Name="directoryList"
MinHeight="100"
Grid.Row="0"
ItemsSource="{Binding Path=SelectedDirectories}"/>
Os SelectedDirectories é uma propriedade nas listas DataContext do tipo List<DirectoryInfo>
A classe que é o datacontext para os implementos de caixa de listagem INotifyPropertyChanged. Quando a coleta muda os itens são adicionados com sucesso à lista no entanto o visor não atualizar até eu forçar a caixa de listagem para redesenhar redimensionando-lo.
Todas as ideias por quê?
EDIT: implementação INotifyPropertyChanged
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));
}
}
}
Solução
Tente
ObservableCollection<DirectoryInfo>
em vez - você está provocando uma atualização de todo o ListBox sem motivo, e você não precisa fazer a sua classe hospedagem implementar INotifyPropertyChanged - poderia facilmente ser apenas uma propriedade da janela. A chave é nunca definir a propriedade para uma nova instância. Assim:
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));
}
}
Se você acabar usando essa classe FileScanner, você precisa implementar INotifyCollectionChanged vez -. Dessa forma, o ListBox sabe o que para adicionar / remover dinamicamente
Outras dicas
(veja update abaixo) . WPF parece estar funcionando bem. I colocar seu código em um novo projeto. As atualizações caixa de listagem sempre que clico no botão para invocar AddDirectory. Você não deve precisar de mais alterações no código. O problema parece ser outra coisa .. Existem vários segmentos em sua interface do usuário?
Eu não tenho o tipo FileScanner. Então, eu criei um manequim da seguinte forma.
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; }
}
Não muda a sua classe FileScannerPresenter. Ou a sua caixa de listagem XAML. Eu criei uma janela com um DockPanel que contém sua caixa de listagem, uma caixa de texto e um botão.
Update: Paul Betts está certo. Ele funciona porque eu voltar uma nova lista de cada vez a partir da propriedade ligados. Ligação de dados com listas sempre mexe-me. Com mais ajustes, a maneira mais fácil de fazer isso é:
- Faça FileScanner # Diretórios retornar um
ObservableCollection<DirectoryInfo>
(que implementaINotifyCollectionChanged
para você). Alterar todas as assinaturas todo o caminho até para retornar esse tipo em vez de umList<DirectoryInfo>
-
FileScanner e FileScannerPresenter si não tem que implementar qualquer interface INotifyXXX.
// 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); } }